[Ren'Py] ระบบต่อสู้จากเกม Guardian Tales - The Behind of Light - dreamknight - 07-07-2014
;3
สวัสดีครับทุกท่าน พอดีมีผู้สนใจวิธีการทำระบบสู้ในเกม Guardian Tales - The Behind of Light แล้วระบบก็ไม่ได้ยากอะไร ผมก็เลยจะมาอธิบายวิธีเขียนให้ทุกท่านที่สนใจอ่านกันครับ
แปะมู้เกมกันเสียเล็กน้อย http://irpg.in.th/thread-1642.html
ขอออกตัวก่อนว่าอันที่จริงผมไม่ได้คิดเองหมด ผมประยุกต์เอาเสียมากกว่า ทุกท่านที่ได้ศึกษา Renpy มาคงได้เข้าไปศึกษาที่เว็บ thaigraph กันใช่ไหมครับ ผมก็เอามาจากที่นั้นแหละ แหะๆ ยังไงก็ขอขอบคุณท่าน NOOKFUFU2 จาก thaigraph ที่มีบทความดีๆ ให้ผมได้ศึกษาครับ ;w;
ช่วงที่พัฒนาขึ้นมานั้น ผมมีเวลาสร้างเกมจำกัดอาจจะเขียนระบบไว้ไม่ดีนัก ทุกท่านก็ลองเอาไปประยุกต์ให้ดีขึ้นแล้วกันครับ
พูดเยอะไปและ เข้าเรื่องดีกว่า. . . อาโน. . พูดเรื่องไรก่อนดีอ่ะ // โดนถีบ
หลอดพลังของตัวละคร
หลอดพลังของทั้งของตัวเอกและของมอน ผมประยุกต์มาจากบทความนี้ครับ วิธีทำ label Fight RPG
แต่ในเกมผมจะเอาแค่หลอดพลังเท่านั้น ก็เอาแต่ ui.bar มาใช้ครับ
Code: init:
python hide:
def score_honor():
if show_score:
ui.bar(max_score_honor, score_honor,
xmaximum=312,
ymaximum=35,
left_bar=Frame("honorgate_full.png", 0, 0),
right_bar=Frame("honorgate_empty.png", 0, 0),
thumb=None,
thumb_shadow=None)
config.overlay_functions.append(score_honor)
def mon_hp():
if show_mon:
ui.bar(mon_max_hp, mon_hp,
xmaximum=312,
ymaximum=21,
left_bar=Frame("mongate_full.png", 0, 0),
right_bar=Frame("mongate_empty.png", 0, 0),
thumb=None,
thumb_shadow=None)
config.overlay_functions.append(mon_hp)
นำ code ด้านบน วางไว้ในไฟล์ .rpy ไฟล์ใดก็ได้ แต่ต้องไม่อยู่ภายใน label screen หรือ init python ใดๆ ส่วนของผมวางไว้ล่างสุดของไฟล์ options.rpy ส่วนรูปหลอดพลังให้หาหรือสร้างเอาเองนะครับ
ui.bar() เป็นฟังก์ชันสร้าง bar ของ Renpy รายละเอียด คลิ๊ก
และมีตัวแปรควบคุมการซ่อน/แสดง หลอดพลังด้วย show_score, show_mon
วิธีใช้
ที่ไฟล์ script.rpy ประการตัวแปร max_hp และ hp ณ ปัจจุบัน สำหรับใช้ใน ui.bar เอาไว้บนสุดของไฟล์ หรือที่เดียวกับตัวแปรพวกตัวละคร(Character) และตัวแปร show_score, show_mon เป็น false เพื่อซ่อนไว้ ไม่ให้เห็นตั้งแต่เริ่มเกม (เวลาแสดงก็แค่เขียน $ show_score = True เวลาซ่อนก็เขียน $ show_score = False)
Code: $ show_score = False
$ show_mon = False
$ max_score_honor = 100
$ score_honor = 0
$ mon_max_hp = 100
$ mon_hp = 0
จะลดพลังของมอน ก็เขียน $ mon_hp -= 5 หรือจะเพิ่มพลังก็เขียน $ mon_hp += 5 ลงไป ($ mon_hp -= 5 กับ $ mon_hp = $ mon_hp - 5 มีความหมายเดียวกัน)
*เกมของผมพระเอกไม่ได้มีหลอดพลัง แต่เป็นแต้มเพิ่มไปเรื่อยๆ จนถึง ค่า max
ระบบสู้
ตัวอย่าง code ระบบสู้ภายในเกม พร้อมเขียนอธิบายไว้ในบรรทัด
Code: $ show_score = True
$ show_mon = True
$ mon_max_hp = 100 # เลือดทั้งหมดของมอน
$ mon_hp = 100 # เลือด ณ ปัจจุบันของมอน
$ actor_attack_point = 1.0 # พลังโจมตีของตัวเอก
$ actor_cri_point = 2.0 # พลังโจมตีติดคริของตัวเอก
$ mon_attack_point = 5 # พลังโจมตีของมอน
$ mon_cri_point = 9 # พลังโจมตีติดคริของมอน
$ hit = False
$ miss = False
speaker "FIGHT !!" # โชว์ข้อความก่อนเข้าลูปสู้
while mon_hp > 0: # วนลูปไปเรื่อยๆ จนกว่าพลังมอนจะเหลือ 0
$ show_score = False # ซ่อนหลอดพลังไว้หรือไม่อยากซ่อนก็เอาออกไป
if miss: # อันนี้เขียนเงื่อนไขดักไว้กรณีเรากดปุ่ม HIT ไม่ทันหรือกดไม่โดน
call expression renpy.random.choice(["mon_hit", "mon_cri"])
# call expression เป็นการใช้เรียกใช้เหตุการณ์ ซึ่งจะไม่เหมือน jump ตรงที่หลังจากจบเหตุการณ์ที่เรียกมาใช้แล้ว จะกลับมารันเหตุการณ์เดิมต่อไป ซึ่งถ้าเป็น jump พอไปอีกเหตุการณ์หนึ่ง ก็จะจบเกมทันที
# renpy.random.choice() ฟังก์ชั่นแรนดอมของ Renpy
$ miss = False
$ hit = False
show screen btnHit(renpy.random.randint(1, 10))
# เข้า screen btnHit()
# renpy.random.randint() เป็นฟังก์ชั่นแรนดอมตัวเลขของ Renpy ในที่นี้แรนดอมเลข 1 ถึง 10
show wyvern_pic at center
with Pause(1.0) # หยุดรอให้เวลาเรากดปุ่ม Hit ที่นี่
hide screen btnHit
if hit == False: # เข้าเงื่อนไขถ้าผู้เล่นกด Hit ไม่ทันหรือกดไม่โดน
play sound "sound/dragonsnarl.mp3"
$ show_score = True
wyvern "! ! ! ! ! ! ! !"
stop sound fadeout 0.5
$ miss = True
# End while
$ show_score = True
wyvern ". . . . . . . . . . . . . . ."
การทำปุ่ม Hit
ปุ่ม Hit หรือ Critical ผมเขียนคล้ายฟังก์ชั่นเอาไว้ ให้ง่ายต่อการใช้
Code: screen btnHit(damage):
if damage <= 7: # เงื่อนไขถ้าน้อยกว่าหรือเท่ากับ 7 ให้โชว์ปุ่ม Hit
hbox:
area (renpy.random.randint(10, 650), renpy.random.randint(10, 300), 1.0, 75)
imagebutton:
idle "hit_damage.png"
hover "hit_damage_hover.png"
action ui.callsinnewcontext("actor_hit")
else:
hbox:
area (renpy.random.randint(15, 650), renpy.random.randint(10, 300), 1.0, 75)
imagebutton:
idle "menu/cri_damage.png"
hover "menu/cri_damage_hover.png"
action ui.callsinnewcontext("actor_cri")
label actor_hit:
show bg_blank with wflash
with sshake
play sound "sound/attack3.ogg"
$ mon_hp = mon_hp - actor_attack_point
$ score_honor += actor_attack_point
$ hit = True
return
label actor_cri:
show bg_blank with wflash
with sshake
play sound "sound/battle3.ogg"
$ mon_hp = mon_hp - actor_cri_point
$ score_honor += actor_cri_point
$ hit = True
return
ui.callsinnewcontext() เอาไว้เรียกใช้ฟังก์ชั่น(เป็น Label) อีกทีหนึ่ง รายละเอียด คลิ๊ก
ส่วน code การโจมตีของมอน ก็เขียนเป็น label แยกไว้แบบตีธรรมดากับตีคริ ตรงนี้ผมไม่อธิบายแล้วกันฮะ เพราะน่าจะเข้าใจกัน
Code: label mon_hit:
show bg_blank with rflash
with sshake
play sound "sound/damage4.ogg"
if score_honor >= 1:
$ score_honor = score_honor - mon_attack_point
else:
$ score_honor = 1
$ hit = True
return
label mon_cri:
show bg_blank with rflash
with sshake
play sound "sound/battle1.ogg"
if score_honor >= 1:
$ score_honor = score_honor - mon_cri_point
else:
$ score_honor = 1
$ hit = True
return
การเขียนระบบสู้ของผมก็มีเพียงเท่านี้ครับ ลองประยุกต์กันดูนะครับ . .
RE: ระบบต่อสู้จากเกม Guardian Tales - The Behind of Light - jin - 07-07-2014
ขอบคุณมากครับท่านฝัน
|