สคริปต์สำหรับกลยุทธ์แบบเทิร์นเบส การพัฒนากลยุทธ์ทีละขั้นตอน ขั้นตอนหลักของการสร้างกลยุทธ์

สวัสดีทุกคน! ตอนนี้ฉันจะบอกคุณถึงวิธีสร้าง RTS แบบง่าย ๆ (RTS - Real Time Strategy นั่นคือกลยุทธ์แบบเรียลไทม์) เปิดเปลญวน 8.1 (ไม่รับประกันการใช้งานใน 8.0) สร้างวัตถุ objControl นั่นคือนี่จะเป็น วัตถุหลักของเรา สร้างเหตุการณ์การสร้าง ( สร้าง) เพิ่มเหตุการณ์ => การสร้าง (เพิ่มเหตุการณ์ => สร้าง) เหตุการณ์การสร้างจะทำเพียงครั้งเดียว - เมื่อสร้างให้คลิกที่แท็บควบคุมในเมนูแนวตั้งด้านขวาและคลิกขวาที่ Execute รหัส (รันโค้ด) และเขียนโค้ด (ทางที่ดีไม่ควรคัดลอกโค้ด และการเขียนโค้ดด้วยตัวเองจะทำให้จำได้ง่ายขึ้นมาก):

200?"200px:"+(this.scrollHeight+5)+"px");">startx=0; // ประกาศตัวแปรสำหรับจุดเริ่มต้นของ x
เริ่มต้น=0; //ประกาศตัวแปรจุดเริ่มต้นของจุดด้วย y
Draw_rect=เท็จ; //อย่าวาดรูปสี่เหลี่ยมสำหรับเลือก


ตัวแปร: ชิ้นส่วนของหน่วยความจำที่มีข้อมูล พวกเขามีชื่อของตัวเองซึ่งคุณสามารถติดต่อได้ ตัวแปรใน GML สามารถประกอบด้วยจำนวนจริงหรือสตริงได้ ตัวอย่างเช่น ตารางเป็นตัวแปร ไม้หรือแก้วเป็นค่า
ตอนนี้เราสร้างเหตุการณ์ขั้นตอน (ขั้นตอน เพิ่มเหตุการณ์ => ขั้นตอน) และดำเนินการอีกครั้ง (คลิกขวาที่ Execute code):

200"200px":"+(this.scrollHeight+5)+"px");">
if mouse_check_button_pressed(mb_left) //ถ้ากด LMB
{
Draw_rect=จริง; // เราวาดรูปสี่เหลี่ยมผืนผ้า
startx=mouse_x; //ตำแหน่งเริ่มต้น x = ตำแหน่งเมาส์ x
เริ่มต้น=mouse_y; //ตำแหน่งเริ่มต้น = ตำแหน่งเมาส์
โดยเลือกทั้งหมด = false; //นี่ไม่ใช่ตัวแปรที่ถูกประกาศ เราจะมาดูกันว่ามันจะทำอะไรในภายหลัง
}

If mouse_check_button_released(mb_left) //หากปล่อย LMB
{
Draw_rect=เท็จ; // เราไม่ได้วาดรูปสี่เหลี่ยม
สำหรับ(i=0;i<=instance_number(par);i+=1) //Читайте про цикл for ниже
{
ii=instance_find(พาร์,ฉัน); //เรากำลังมองหาวัตถุที่ยังไม่ได้ทำ
if(collision_rectangle(startx,starty,mouse_x,mouse_y,ii,true,false)) //นี่คือสี่เหลี่ยมการชนกันของเรา (หน้าสัมผัส)
{
ii.selected=true;
}
}
}

โค้ดมีขนาดใหญ่และซับซ้อนในขณะที่เราเรียนรู้เกี่ยวกับคำสั่ง if Conditional:
รหัสที่มี if ถูกดำเนินการดังนี้:

200"200px":"+(this.scrollHeight+5)+"px");">
ถ้า (เงื่อนไข)
{
การกระทำ
}

นอกจากนี้ยังอาจมีคำสั่ง else (มิฉะนั้น) ตัวอย่าง:

200"200px"""+(this.scrollHeight+5)+"px");">ถ้า (เงื่อนไข)
{
การกระทำ
}
อื่น
{
การกระทำ 2
}

และสำหรับ เป็นตัวดำเนินการลูป มันถูกดำเนินการดังนี้:

200"200px":"+(this.scrollHeight+5)+"px");">
สำหรับ (<переменная> ; <выражение> ;<действие переменной>)
{
<действия>
}


ตัวดำเนินการ for เป็นสิ่งที่ทรงพลังมาก ซึ่งช่วยได้มากในสถานการณ์ที่ยากลำบาก

โอเปอเรเตอร์ - การกระทำที่สร้างขึ้นในภาษา ตัวอย่างเช่น การกระทำที่พบบ่อยที่สุดคือ int, if, else, string, switch, for, case, break, exit ฯลฯ

ตอนนี้เรายังสร้างกิจกรรมการวาดภาพ (วาด) และเขียนในลักษณะเดียวกัน:

200"200px":"+(this.scrollHeight+5)+"px");">ถ้า Draw_rect=true
{
อัลฟา=.8;
Draw_rectangle_color(startx,เริ่มต้น,mouse_x,mouse_y,c_green,c_green,c_green,c_green,true);
}

ทุกอย่างเป็นเรื่องง่ายที่นี่ นี่เป็นสิ่งเดียวกันในภาษารัสเซียเท่านั้น:
ถ้าเราต้องการวาดรูปสี่เหลี่ยม เราก็เลือกความโปร่งใสแล้ววาดรูปสี่เหลี่ยม
นี่คือข้อโต้แย้ง

200?"200px:"+(this.scrollHeight+5)+"px");">draw_rectangle_color(x1,y1,x2,y2,สี 1, สี 2, สี 3, สี 4, โครงร่าง)


โครงร่าง - ไม่ว่าจะวาดเฉพาะขอบ (จริง) หรือสี่เหลี่ยมที่เติม (เท็จ)
เราพบคำใหม่ - ค่าคงที่ นี่คือนิพจน์ตัวเลขหรือรหัสที่แทนที่ด้วยคำ เปลญวนมีค่าคงที่ในตัว:

200"200px":"+(this.scrollHeight+5)+"px");">จริง - 1
เท็จ - 0
ปี่ - 3.1415...


เราเข้าใจแล้ว ตอนนี้เราต้องสร้าง วัตถุใหม่- วัตถุแม่ที่จะเชื่อมต่อกับลูก ๆ ของมัน เรียกมันว่าพาร์ (หากต้องการเปลี่ยนชื่อที่คุณต้องเปลี่ยนรหัสในเหตุการณ์ขั้นตอนของอ็อบเจ็กต์ควบคุม) ให้เขียนในเหตุการณ์การสร้าง:

200?"200px:"+(this.scrollHeight+5)+"px");">selected=false; //นี่คือตัวแปรของเรา ไม่ว่าวัตถุจะถูกเลือกหรือไม่

นี่คือทั้งหมด. แน่นอนว่าตอนนี้เราต้องการวัตถุที่สามารถเคลื่อนที่ได้ ซึ่งเราเรียกว่า objTest และเขียนโค้ดในเหตุการณ์การสร้าง:

200">gox=x; //จะไปไหน...
goy=y; //โดยคุณ
เลือก=เท็จ; //เราไม่ได้ถูกเลือก=)
object_set_parent(self,par) //นี่คือตัวเลือกของ parent

การกระทำใหม่:

200?"200px":"+(this.scrollHeight+5)+"px");">object_set_parent(ind,obj)

ตั้งค่าวัตถุหลักให้กับวัตถุชื่อ ind
และ ผู้ดำเนินการใหม่: self แปลว่า การกระทำนั้นจะไปสู่ตัวมันเอง
อย่ากลัว ยังเหลือกิจกรรมขั้นตอนอีกเล็กน้อย:

200"200px":"+(this.scrollHeight+5)+"px");">ถ้า Distance_to_point(gox,goy) > 20
{
mp_potential_step(gox,goy,6,ทึบ);
}
ถ้า (เลือก = true) && mouse_check_button_pressed (mb_right)
{
gox=mouse_x;
goy=mouse_y;

สวนสนุก:
ฉันเราต้องการ:
สไปรท์อาคาร
เมนูสไปรท์
สไปรต์ของปุ่มต่างๆ เช่น:
srite พร้อมจารึก (การก่อสร้าง, การก่อสร้าง, การสร้าง ฯลฯ )
หน้าต่างที่ปรากฏขึ้น
การเขียนแบบอาคาร,
1) เราจะเพิ่มส่วนที่เหลือเอง
2)คำว่าของปลอม-สร้างเองเพราะว่า เราจะต้องปลอมมันเพื่อให้ตรงกับแหล่งที่มาของเรา)
II มาเริ่มกันเลย:
1) สร้างทุกสิ่งที่เขียนในจุดที่ 1 ยกเว้น 1)
เรามาสร้างตัวแปรโกลบอลที่เรียกว่า เงิน กำหนดจำนวนเงินเริ่มต้นกัน
เราจะสร้างวัตถุเมาส์และคีย์บอร์ดด้วย
มาสร้างข้อความ เรียกมันว่าข้อมูล สร้างกิจกรรมตลอดเวลา และสร้างการกระทำในนั้น:
เลือกข้อมูลในการดำเนินการ เลือก เลือกตั้งค่าข้อความในข้อความ เขียนสิ่งนี้:
"เงิน: " &(ทั่วโลก ("เงิน".
2) เพิ่มเมนู งานหลักของเมนูไม่ใช่การรบกวน แต่เพื่อช่วยให้ผู้เล่นนำทาง (มันจะรบกวนได้อย่างไร - มันง่ายถ้าคุณวางไว้ตรงกลางเกม) ก่อนทำเมนูเรา จะสร้างเลเยอร์ใหม่ซึ่งเราจะเรียกว่าเมนูตามสัดส่วน ( การตั้งค่า ตัวเลือก) ในรายการแสดงผลที่เราเขียน:


เราจะเพิ่มสไปรท์เข้าไปและนำรูปภาพของเมนูที่อยู่ในเอกสารก่อนการผลิต (จุดที่ 1) และวางเมนูของเราไว้ในที่ที่เงียบสงบซึ่งจะไม่รบกวน แต่จะมองเห็นได้บนหน้าจอ
เรามาวางปุ่มที่ทำจากวัสดุสำเร็จรูป (จุดที่ 1) พร้อมกับคำจารึกว่า BUILD (หรืออะไรทำนองนั้น)
มาใส่ไว้ในเมนูกันดีกว่า
ตอนนี้ไปที่ตัวแก้ไขแผ่นงานเหตุการณ์
สร้างกิจกรรม (#blah blah blah# - นี่คือข้อความของฉัน (คำอธิบาย) ถึงคุณเท่านั้น แทนที่จะเป็น blah blah blah จะมีความคิดเห็นของฉันสำหรับคุณ >> - action; ll - การแบ่งหน้าต่างเช่น:

เมาส์&คีย์บอร์ด ll บนวัตถุที่ถูกคลิก ll คลิกซ้ายเพื่อวัตถุ #ปุ่มเมนูของคุณพร้อมข้อความ BUILD (หรืออะไรทำนองนั้น)##ส่วนที่เหลือในภายหลัง (ดูจุดที่ 3)#
3)ตอนนี้ส่วนที่ยากที่สุด(ผมแบ่งเรื่องนี้ออกเป็นสองประเด็นเพื่อไม่ให้ซับซ้อนมาก)
สร้างสไปรท์จากวัสดุตกแต่งสำเร็จ “หน้าต่างที่จะปรากฏขึ้น”
จากนั้นเราจะสร้างสไปรต์ว่างที่เรียกว่า p1 ย้ายหน้าต่างออกจากหน้าจอ และวาง p1 ในตำแหน่งที่หน้าต่างของคุณควรปรากฏขึ้นเมื่อคุณกดปุ่มสร้าง (หรืออะไรทำนองนั้น CHVER)
เยี่ยมมาก! ตอนนี้ไปที่เครื่องมือแก้ไขแผ่นงานกิจกรรม
มาเขียนเหตุการณ์ที่ยังไม่เสร็จให้จบ:
ข้อความจะตั้งค่าข้อความ ll bla-bla-bla)
เมาส์&คีย์บอร์ด ll บนวัตถุที่ถูกคลิก ll คลิกซ้ายเพื่อวัตถุ #ปุ่มเมนูของคุณที่มีป้ายกำกับ BUILD (หรืออะไรทำนองนั้น)#>>
4)ส่วนที่สองของส่วนที่ยากที่สุด:
มาสร้างสไปรท์ที่จะวาดภาพอาคาร (วัสดุก่อนตกแต่ง) กันดีกว่า เรียกว่า h1
มาสร้างสไปรท์ว่างๆ เรียกมันว่า p2 กัน ตอนนี้วางไว้ในตำแหน่งที่หน้าต่างควรเปิด
มาสร้างสไปรท์รวมถึงหน้าต่าง (วัสดุตกแต่งล่วงหน้า) ในหน้าต่างเราจะเขียนชื่ออาคารราคาและคำอธิบาย (ไม่จำเป็น) ในหน้าต่างอย่างสวยงามแล้วเรียกมันว่า i1
มาสร้างสไปรต์ว่างอีกตัวที่เรียกว่า p3 วางไว้ข้าง p2 เพียงเพื่อให้แตะ p2 ด้วยมุมซ้ายบนเท่านั้น
ตอนนี้เรามาสร้างกิจกรรมต่างๆ กัน แต่ก่อนอื่น เราทำให้กิจกรรมก่อนหน้านี้เป็นการกระทำใหม่:
เมาส์&คีย์บอร์ด ll บนวัตถุที่ถูกคลิก ll คลิกซ้ายเพื่อวัตถุ #ปุ่มของเมนูของคุณพร้อมข้อความ BUILD (หรืออะไรทำนองนั้น)#>> ระบบจะสร้างวัตถุที่สัมพันธ์กับวัตถุ ll #หน้าต่างของคุณ# #หมายเลขเลเยอร์ใต้ชื่อเมนู# # X ;Y-อย่าเปลี่ยน# เป็นวัตถุ p1
>>ระบบจะสร้างวัตถุที่สัมพันธ์กับวัตถุ ll #หน้าต่างที่สองของคุณ# #หมายเลขเลเยอร์ใต้เมนูชื่อ# #X;Y-อย่าเปลี่ยน# เป็นวัตถุ p2
เราต้องคืนกิจกรรมให้เขาด้วย:
คัดลอกเหตุการณ์และกลับด้าน
กิจกรรมใหม่
mouse&keyboard ll อยู่เหนือวัตถุ ll h1>>ระบบจะสร้างวัตถุให้สัมพันธ์กับวัตถุ ll i1 #หมายเลขเลเยอร์ภายใต้ชื่อเมนู# #X;Y-อย่าเปลี่ยน# เป็นวัตถุ p3
มาสร้างสไปรท์กับสิ่งปลูกสร้าง (ใช้วัสดุก่อนการผลิต) แล้วเรียกมันว่าบ้านกันดีกว่า
มาสร้างหน้าต่างที่อาคารของเราจะปรากฏขึ้นเมื่อเลือกในเมนู เรียกว่า rlo
กิจกรรม:
เมาส์&คีย์บอร์ด ll บนวัตถุคลิก ll คลิกซ้ายเพื่อ h1>>ระบบ ll สร้างวัตถุสัมพันธ์กับวัตถุ ll บ้าน #หมายเลขเลเยอร์ภายใต้ชื่อเมนู# #X;Y-อย่าเปลี่ยน# เป็นวัตถุ rlo
>> ระบบจะลบออกจากมูลค่า ll #จำนวนเงินที่ควรเอาไประหว่างการก่อสร้าง#
ตอนนี้ไม่สามารถสร้างงานได้
ฉันจะบอกคุณของฉัน วิธีเดิมข้อห้าม (เมื่อฉันเขียนเสร็จฉันจะสำรวจวิธีอื่นที่ทำให้ฉันเศร้าเมื่อนึกถึงเกมสวนสนุกโลก)
กิจกรรม:
บ้านจะชนกับวัตถุอื่นจะเข้าบ้าน
>>บ้านจะพัง
>> ระบบ ll ลบออกจากค่า ll - #สองเท่าของจำนวนเงินที่เอาไประหว่างการก่อสร้าง##หมายเหตุคุณต้องใส่ - ปริมาณ#
โดยพื้นฐานแล้วทุกอย่าง
III สิ่งที่ฉันต้องการจะพูด:

ฉันเสียใจมากกับการล่มสลายของเกม มันเป็นเกมแนววางแผนและบทความนี้รวบรวมตามโครงร่าง ฉันขอให้คุณอย่าวิพากษ์วิจารณ์มากเกินไปฉันเขียนมานานแล้วหากคุณพบข้อผิดพลาดในการพูด เขียนแล้วฉันจะแก้ไขให้ถูกต้อง
และนี่คือซอร์สโค้ดเพื่อความเพลิดเพลินในการรับชมของคุณ ดูสิ โดยหลักการแล้วทุกอย่างเหมือนกับที่เขียนไว้ที่นี่ นี่เป็นเพียงเวอร์ชันสาธิตของเกมเท่านั้น สิ่งสำคัญคือไม่ต้องเปลี่ยนแปลงอะไรเลย ไม่เช่นนั้นมันจะบั๊กกี้ !
ใช้มัน ทดลอง ตรวจสอบ ทำตามที่คุณต้องการ ทุกอย่างมันใช่สำหรับฉัน

กามิกาซ่า:
นิพจน์ "ระบบ" ทั้งหมดต้องรวมอยู่ในแท็ก "โค้ด"
แล้วคิดว่ามันจะดีขึ้น
สำหรับฉันแล้วดูเหมือนว่าภาพหน้าจอจะไม่เจ็บที่นี่ และซอร์สโค้ดสำหรับผู้เริ่มต้นด้วย

สวนสนุก:
ฉันไม่รู้วิธีจับภาพหน้าจอของกิจกรรม

นั่นไม่จำเป็นเลย

ฉัน:
theme_park มีปุ่มพิเศษบนแป้นพิมพ์ - PrintScreen

สวนสนุก:
ฉันรู้ว่าบางคนทำมันแตกต่างออกไป ยิ่งกว่านั้น ทุกคนมีสปิริตของตัวเอง
และถ้าฉันสร้างสไปรท์เหล่านี้ขึ้นมา ก็จะมีน้อยคนที่เข้าใจ
บางทีอาจมีคนให้ข้อดีบ้าง? ไม่น่าแปลกใจที่ฉันกำลังดิ้นรน?

เบอร์ลาเชนโก:
เพื่อให้บทเรียนดังกล่าวเป็นที่สนใจของใครก็ตาม จำเป็นต้องจัดรูปแบบบทเรียนให้เหมาะสม แต่ที่นี่ “อย่างไรก็ตาม”
และถ้าคุณต้องการ ทีละน้อย เมื่อคุณมีเวลา โปรด "ตกแต่ง" มัน

สวนสนุก:
โอเค ฉันจะกลับบ้านจากโรงเรียนและเตรียมตัวให้พร้อม
ป.ล. เพิ่มแหล่งที่มา

เซเรกา เลเบเดฟ:

iamnp ภาพหน้าจอเหล่านี้ไปอยู่ที่ไหนในภายหลัง?

กามิกาซ่า:

ไปที่คลิปบอร์ด
ไปอันไหนก็ได้ โปรแกรมแก้ไขข้อความและดำเนินการ "วาง" หรือกด Ctrl+V

ในบทความนี้ ฉันไม่น่าจะพูดถึงสิ่งที่ไม่รู้จักเลย การคำนวณทั้งหมดนั้นง่ายและเข้าใจได้สำหรับทุกคนที่รู้ว่า Ajax คืออะไร ฉันได้เขียนบทความเกี่ยวกับวิธีรวมไคลเอนต์กับเซิร์ฟเวอร์ในเกมเรียลไทม์ () แล้ว ในบทความนี้ ฉันได้กล่าวถึงปัญหาเดียวกันกับที่ใช้กับเกมแบบผลัดกันเล่น

แล้วอะไรล่ะ เกมเทิร์นเบส- คำจำกัดความต่อไปนี้สามารถพบได้ใน Wikipedia กลยุทธ์เทิร์นเบส - นี่คือประเภท เกมส์คอมพิวเตอร์คุณสมบัติหลักคือผู้เล่นผลัดกันเคลื่อนไหว ซึ่งต่างจากกลยุทธ์แบบเรียลไทม์- ฉันจะลดความซับซ้อนของคำจำกัดความนี้ลงเล็กน้อย:

  • กลยุทธ์ทีละขั้นตอน - เป็นเกมกลยุทธ์แบบเทิร์นเบส.
  • เกมกลยุทธ์ - นี่คือประเภทของเกมที่กุญแจสำคัญในการบรรลุชัยชนะคือการวางแผนและการคิดเชิงกลยุทธ์.
  • เกมเทิร์นเบส - เป็นเกมประเภทหนึ่งที่มีคุณสมบัติหลักคือผู้เล่นผลัดกันเคลื่อนไหว.
เกมผลัดกันเล่นได้แก่:
  • กลยุทธ์แบบเทิร์นเบส
  • การ์ดเกม
  • เกมกระดาน (หมากรุก เกมหมากรุก การผูกขาด ฯลฯ)
ฉันทราบว่าเกมแบบผลัดกันเล่นมีข้อจำกัดด้านความซับซ้อนของโปรโตคอลการโต้ตอบน้อยกว่าเมื่อเปรียบเทียบกับเกมแบบเรียลไทม์ กล่าวคือ เวลาตอบสนองต่อเหตุการณ์ใดเหตุการณ์หนึ่งไม่ได้มีบทบาทสำคัญ- โดยปกติผู้เล่นจะมีเวลา 10 วินาทีในการตัดสินใจ แม้ว่าการปิงจะใหญ่โต เช่น 3 วินาที ผู้เล่นยังคงมีเวลาคิดอีก 7 วินาที นอกจากนี้ ping สามารถกระโดดและกระโดดได้ แต่เราไม่สนใจเรื่องนี้เลย (ในเกมเรียลไทม์ สถานการณ์นี้แทบจะทำลายโปรโตคอลใด ๆ เลย)

โดยทั่วไป (ใน 95% ของเกมแบบเทิร์นเบส) ผู้เล่นหนึ่งคนจะตัดสินใจในเวลาใดก็ตาม ด้วยเหตุนี้ จำนวนคำขอที่เราต้องตอบสนองอย่างเพียงพอจึงลดลง

ดังนั้น เมื่อสร้างโปรโตคอล เราจะมุ่งเน้นไปที่ความง่ายในการใช้งานและการสนับสนุนเป็นหลัก สิ่งนี้จะทำให้เราสามารถทำกำไรได้มากขึ้นโดยใช้เวลาน้อยลง

เหตุผลข้างต้นอิงจากการพัฒนาเกมไพ่บางเกมเป็นเวลา 2 เดือน

ลูกค้าฉลาดหรือโง่?

ขั้นแรก มาตัดสินใจว่าลูกค้าของเราจะ "ฉลาด" แค่ไหน ฉันกำลังถกเถียงว่ามันคุ้มค่าที่จะทำซ้ำตรรกะของแอปพลิเคชัน (กฎของเกม) บนไคลเอนต์หรือไม่ แน่นอนว่าเซิร์ฟเวอร์จะต้องชาญฉลาดเพื่อป้องกันการแฮ็กแอปพลิเคชันที่อาจเกิดขึ้น แต่มันคุ้มค่าที่จะสอนตรรกะทางธุรกิจให้กับลูกค้าหรือไม่?

ขึ้นอยู่กับจำนวนข้อมูลทั้งหมดเกี่ยวกับสถานะของเกมของคุณโดยตรง หากข้อมูลจำนวนนี้มีขนาดใหญ่ ใช้เวลานานในการเก็บรวบรวมบนเซิร์ฟเวอร์ และถูกโอนไปยังไคลเอ็นต์ ดังนั้นจึงสมเหตุสมผลที่จะนำตรรกะบางส่วนไปใช้บนไคลเอ็นต์เพื่อลดภาระของเซิร์ฟเวอร์ ตัวอย่างเช่น ใน Civilization เกจหน่วยความจำที่ใช้จะไม่ได้อยู่ในแผนภูมิเสมอ คุณสามารถสร้างสิ่งที่คล้ายกันโดยเหลือเพียง UI บนไคลเอนต์ได้หรือไม่?

ในทางกลับกัน ยิ่งลูกค้าฉลาดเท่าไหร่ การพัฒนาเกมก็จะยิ่งมีราคาแพงมากขึ้นเท่านั้น โปรดทราบว่าเวลาในการพัฒนาเซิร์ฟเวอร์ไม่ได้ขึ้นอยู่กับความรู้ของลูกค้าแต่อย่างใด แม้ว่าไคลเอนต์จะฉลาดล้ำเลิศ แต่หากผู้ใช้ต้องการโหลดหน้าต่างเบราว์เซอร์ใหม่ เซิร์ฟเวอร์จะต้องรวบรวมและรวบรวมข้อมูลทั้งหมดเกี่ยวกับเกมเพื่อถ่ายโอนไปยังไคลเอนต์ A la "กำลังโหลดเกมที่บันทึกไว้" สรุป: ไคลเอ็นต์อัจฉริยะสามารถเพิ่มความเร็วให้กับแอปพลิเคชันได้ แต่จะต้องใช้ทรัพยากรเพิ่มเติมเพื่อพัฒนาแอปพลิเคชันเสมอ

ฉันแนะนำต่อไปนี้ ทดสอบ:

1. ระดับเสียงของช่องอนุญาตหรือไม่?

ประมาณน้ำหนักเฉลี่ยของข้อมูลสถานะเกมทั้งหมด จากนั้น คูณด้วยจำนวนคำขอโดยเฉลี่ยที่ส่งไปยังเซิร์ฟเวอร์ต่อวินาที หากจำนวนผลลัพธ์เกินความจุช่องข้อมูลขาออก แสดงว่าไคลเอ็นต์ที่โง่เขลานั้นไม่สามารถยอมรับได้ หากจำนวนนี้เกิน 20% ของช่องทางขาออกก็ควรพิจารณาว่าจะได้ผลหรือไม่?

2. ใช้แรงงานเข้มข้นหรือไม่?

ประมาณความซับซ้อนของอัลกอริธึมการรวบรวมข้อมูลเกม (เป็นเศษส่วนของวินาที) ที่นี่ คำนึงถึงแบบสอบถามทั้งหมดไปยังฐานข้อมูล จากนั้น คูณด้วยจำนวนคำขอโดยเฉลี่ยที่ส่งไปยังเซิร์ฟเวอร์ต่อวินาที หากเวลาเกินหนึ่งวินาที ลูกค้าที่โง่เขลาจะยอมรับไม่ได้ หากตัวเลขนี้เกิน 200 ms คุณควรพิจารณาว่าจะคงอยู่หรือไม่

ความต่อเนื่อง:

การก่อตัวของกลยุทธ์
คุณไม่สามารถไว้วางใจมือสมัครเล่นได้:
แผนการของพวกเขาอาจสำเร็จโดยไม่คาดคิด
และไม่มีใครพร้อมสำหรับเรื่องนี้

(อ. คันนิงแฮม)

ในสองประเด็นก่อนหน้านี้เราได้เรียนรู้ สร้างเกม 2D ง่ายๆควบคุมสไปรท์ เลื่อนหน้าจอเกม ติดตามการชนกันของวัตถุในเกม สร้างอินเทอร์เฟซ (ปุ่ม เมาส์ คีย์บอร์ด พื้นที่ข้อความ) และทำงานในโหมดเต็มหน้าจอและโหมดหน้าต่าง ทั้งหมดนี้ทำโดยใช้เกมอาร์เคดเป็นตัวอย่าง

คราวนี้เราจะเปลี่ยนจากเกมอาร์เคดไปเป็นประเภทที่ "จริงจัง" มากขึ้น - กลยุทธ์ ที่นี่เราจะต้องฝึกฝนกลไกใหม่ทั้งชุด แต่จะไม่มีอะไรซับซ้อนที่นี่เช่นกัน ในบทความนี้เรา มาศึกษาโครงสร้างของกลยุทธ์แบบเทิร์นเบสกัน(และนอกจากนี้ยังมี กลยุทธ์เรียลไทม์- ทำได้ง่ายกว่าด้วย LKI-Creator) และเราจะสร้างเกมเป็นตัวอย่าง ออกแบบมาเฉพาะสำหรับ ผู้ใช้หลายคนโหมด (และยัง เครื่องมือแก้ไขแผนที่สำหรับเธอ). เราจะพูดถึงโหมดผู้เล่นเดี่ยวในคอลัมน์ฉบับถัดไปของเราซึ่งมีไว้สำหรับโดยเฉพาะ พื้นฐาน ปัญญาประดิษฐ์ .

เนื่องจากนี่เป็นบทเรียนที่สามแล้ว เราจะไม่ลงรายละเอียด ทั้งหมดโค้ดตัวอย่าง - โชคดีที่มีการดำเนินการหลายอย่างเหมือนกับสองครั้งก่อนหน้านี้ทุกประการ เพื่อเป็นข้อมูลอ้างอิง มีตัวอย่างโปรแกรม (มีคอมเมนท์มากมาย) และบทความก่อนหน้านี้

คุณสามารถค้นหาสื่อการสอนจากชั้นเรียนที่ผ่านมาของเราได้บนเว็บไซต์ของเรา ซีดีในส่วน "เกมทำเอง" ที่สร้างขึ้นโดยเฉพาะเพื่อจุดประสงค์นี้

การกำหนดปัญหา

มาเขียนเกมวางแผนที่ประกอบด้วยการต่อสู้ระหว่างสองกองทัพแฟนตาซีกัน เป้าหมายของการต่อสู้คือการยึดหลาย ๆ อัน เสาโอเบลิสค์, วางไว้บนแผนที่. ก่อนการรบเราจะจัดกำลังทหารซึ่งประกอบด้วย 6 นาย นักดาบ, 4 นักธนู, 2 อัศวิน, 2 นักมายากลและ 1 ผีภายในอาณาเขตที่จัดสรรให้เรา นอกจากนั้น ยังมีสิ่งที่เป็นกลางบนแผนที่ด้วย มังกร.

ลักษณะของนักสู้
นักสู้ ความเคลื่อนไหว ฮิต พิสัย ความเสียหาย การป้องกัน ความสามารถ
นักดาบ4 8 1 7 2 -
อาร์เชอร์4 5 7 5 1 -
อัศวิน3 15 1 9 4 การรักษา การจู่โจมของอัศวิน
นักเวทย์3 12 5 6 0 ลูกไฟ
ผี4 7 2 5 5 การฟื้นฟู
มังกร6 30 2 12 5 เที่ยวบิน

ลักษณะของนักสู้แสดงอยู่ในตาราง การรักษา- นี่คือสิทธิ์ในการรักษานักรบที่อยู่ใกล้เคียง (ยกเว้นผี) ให้มีพลังชีวิตเต็มหนึ่งครั้งต่อการต่อสู้ การโจมตีของอัศวิน- สิทธิ์ในการสร้างความเสียหายสามเท่าหนึ่งครั้งต่อเกม ลูกไฟ- การโจมตีของนักเวทย์จะลบพลังชีวิตไม่เพียงแต่จากเป้าหมายทันที แต่ยังรวมถึงสี่เหลี่ยมโดยรอบด้วย การฟื้นฟู- ฟื้นฟู 1 ครั้งต่อเทิร์น เที่ยวบิน- สิทธิในการก้าวข้ามสิ่งกีดขวาง

เกมนี้เล่นในโหมดผู้เล่นหลายคนในเวอร์ชัน Hot Seat (เล่นจากคอมพิวเตอร์เครื่องหนึ่ง สลับกันทีละคน) หลังจากที่ผู้เล่นหมุน มังกรที่เป็นกลางจะผลัดกันโจมตีศัตรูที่อยู่ในรัศมี 7 ช่อง

ปาร์ตี้จะจบลงเมื่อฝ่ายใดฝ่ายหนึ่งยึดเสาโอเบลิสก์ได้มากกว่าครึ่งหนึ่งบนแผนที่หรือตายสนิท

แผนที่ถูกตั้งค่าครั้งแรกในตัวแก้ไขแผนที่ มีเสาโอเบลิสก์ มังกร และสิ่งกีดขวาง (วัตถุที่คุณไม่สามารถเคลื่อนที่หรือโจมตีได้)

การเตรียมงาน

ก่อนที่เราจะเริ่ม เราจะต้องติดตั้งแพ็คเกจใหม่ก่อน LKI-ผู้สร้าง- ความจริงก็คือเมื่อเปรียบเทียบกับครั้งที่แล้วมีการเปลี่ยนแปลงและเพิ่มเติมมากมาย

(ฉันหวังว่า เดลฟีคุณได้ติดตั้งแล้ว ถ้าไม่เช่นนั้นให้อ่านคำแนะนำในหัวข้อนี้ในบทความก่อนหน้าของเรา - ในนิตยสารฉบับเดือนมิถุนายนหรือในซีดีของฉบับนี้หรือบนเว็บไซต์)

มันเป็นสิ่งสำคัญ: LKI-Creator เวอร์ชันก่อนหน้ามีปัญหาความเข้ากันได้กับ Delphi เวอร์ชันใหม่ ในเวอร์ชันนี้พวกเขาจะถูกตัดออก

นำไฟล์พร้อมข้อความโปรแกรมและรูปภาพจากซีดีของเรา (หัวข้อ "เกมด้วยมือของคุณเอง") แล้วแตกลงในไดเร็กทอรีโครงการ

ตอนนี้คุณสามารถดาวน์โหลดได้แล้ว ไฟล์ที่จำเป็น จากที่นี่ .

เราควรมีสามไดเรกทอรีย่อย หนึ่ง - หน่วย - เก็บไลบรารี DirectX และโมดูลของแพ็คเกจ LKI-Creator ในอีกโครงการ - เราจะทำงาน รูปภาพที่เราต้องการจะถูกวางไว้ล่วงหน้าและ รุ่นก่อนหน้าอาร์เคดของเรา ในส่วนที่สาม - Escort - โปรแกรมสำเร็จรูปที่เราควรประสบความสำเร็จ

ตอนนี้มาติดตั้ง (ติดตั้งใหม่) LKI-Creator ในเมนู Delphi ให้เปิดรายการ Component และเลือก Install Component หากคุณได้ติดตั้งแพ็คเกจนี้แล้ว ให้อยู่ในแท็บ Into existing package หรือไปที่แท็บ Into new package แล้วกรอกบรรทัดว่างดังแสดงในรูป (ในบรรทัดบนสุด วิธีที่ง่ายที่สุดคือเลือก LKI2dEngine pas โดยใช้ปุ่มเรียกดู และที่ด้านล่างสุดให้จด LKI) จากนั้นคลิกตกลงและเลือกติดตั้ง ใน แผงด้านบน Delphi คุณควรเห็นแท็บ LKI

ตอนนี้สิ่งที่เหลืออยู่คือการอัปโหลดโครงการของเรา ในเมนูไฟล์ เลือกเปิด เปิดไฟล์ Project\Obelisk.dpr...

แผนที่อยู่ไหน บิลลี่? เราต้องการแผนที่!

อย่างไรก็ตาม ก่อนที่เราจะพูดถึงเรื่องใหญ่ เราจะต้องปรับปรุงเอ็นจิ้นกราฟิกเพิ่มเติมอีกเล็กน้อย

ใน Star Escort ซึ่งเป็นโปรเจ็กต์ก่อนหน้าของเรา "แผนที่" ไม่มีความหมาย: ดาวต่างๆ ถูกวางแบบสุ่มและไม่มีผลกระทบใดๆ และตำแหน่งของวัตถุอื่นๆ จะถูกระบุโดยตรงในโค้ดหรือกำหนดโดยบังเอิญ สิ่งนี้ไม่เหมาะกับทุกโครงการ ซึ่งหมายความว่าถึงเวลาที่เราต้องเพิ่มเข้าไปในเครื่องยนต์ของเรา แผนที่พื้นที่.

คุณคงเดาได้แล้วว่ามันจะเป็นอย่างไร - เราวางวัตถุแผนที่ไว้ที่หน้าต่างโปรเจ็กต์ จากนั้นลงทะเบียนในคุณสมบัติ แผนที่เครื่องยนต์ของเรา

เป็นเช่นนั้น... แต่เรามีการ์ดมากกว่าหนึ่งคลาส มาดูกันดีกว่า...

ประเภทของการ์ด

แผนที่ประกอบด้วยบางสิ่งบางอย่าง ภูมิประเทศและ วัตถุติดตั้งไว้บนนั้น ภูมิทัศน์ส่วนใหญ่มัก (แต่ไม่เสมอไป) แบ่งออกเป็นเซลล์ที่เรียกว่า กระเบื้อง- กระเบื้อง.

ดังที่เราทราบจากหลักสูตรเรขาคณิตของโรงเรียน สามารถคลุมระนาบได้โดยไม่มีช่องว่างหรือซ้อนทับกับรูปหลายเหลี่ยมปกติสามประเภท ได้แก่ สามเหลี่ยม (ด้านเท่ากันหมด) สี่เหลี่ยมจัตุรัส และหกเหลี่ยม ช่องสามเหลี่ยมไม่สะดวกเป็นพิเศษ ดังนั้นจึงมักใช้เซลล์สี่เหลี่ยมหรือรูปหกเหลี่ยมมากกว่า

ในแง่หนึ่ง การมีชีวิตอยู่กับสี่เหลี่ยมนั้นง่ายกว่า หากเรามีอาร์เรย์ของเซลล์สองมิติ ก็จะชัดเจนทันทีว่าจะค้นหาเซลล์ที่อยู่ติดกับเซลล์ที่กำหนดได้อย่างไร นี่คือ +1 และ -1 สำหรับแต่ละดัชนีทั้งสอง เมื่อใช้รูปหกเหลี่ยม ทุกอย่างจะซับซ้อนขึ้นเล็กน้อย... แต่กระดานหกเหลี่ยมมีคุณสมบัติที่มีค่ามาก: ทุกทิศทางในนั้นเหมือนกัน นี่ไม่ใช่กรณีของตารางสี่เหลี่ยม เนื่องจากเส้นทแยงมุมมีความแตกต่างอย่างมากจากแนวนอนและแนวตั้ง ดังนั้น สำหรับการคำนวณเชิงกลยุทธ์อย่างจริงจัง รูปหกเหลี่ยมอาจดีกว่ากำลังสอง

นอกจากนี้ยังมีการ์ดที่ไม่เรียงต่อกัน LKI-Creator รองรับสองประเภท: กราฟและการเย็บปะติดปะต่อกัน

แผนที่กราฟเป็นแผนที่ที่มีจุดสำคัญเพียงไม่กี่จุดเท่านั้นที่มีความหมาย บวกกับพื้นที่พิเศษ (เช่น พื้นที่ที่ไม่สามารถผ่านได้) และส่วนที่เหลือเป็นเพียงรูปแบบที่ไม่มีเอฟเฟกต์ของเกม นี่เป็นวิธีที่มักสร้างแผนที่ดาว อย่างเช่นใน Master of Orion: ดาวและหลุมดำเป็นจุดสำคัญ ส่วนที่เหลือเป็นพื้นหลัง ในโหมดนี้ บางครั้งพวกเขาจะสร้างแผนที่ทั่วโลก เช่น สำหรับเกมเล่นตามบทบาท

แผนที่การปะติดปะต่อแบ่งออกเป็นพื้นที่ และภายในพื้นที่ทุกจุดจะเหมือนกัน คุณไม่สามารถเคลื่อนที่ไปตาม "การปะติดปะต่อ" นี่เป็นสิ่งที่ดีสำหรับกลยุทธ์ระดับโลก โดยที่จังหวัดเป็นหน่วยอาณาเขตขั้นต่ำ

ตัวอย่างไพ่จากเกมต่างๆ ระบุประเภท อยู่ในรูปภาพ

ดังนั้นคนส่วนใหญ่ สองมิติแผนที่ (สามมิติ - บทความพิเศษ) สามารถแบ่งออกเป็นสี่คลาส:

  • สี่เหลี่ยม- TLKIRectMap- นี่คือแผนที่แบบเรียงต่อกัน เซลล์ต่างๆ เป็นรูปสี่เหลี่ยม ตัวอย่างเช่นแผนที่ดังกล่าวใน Civilization III
  • หกเหลี่ยม- TLKIHexMap- แผนที่แบบเรียงต่อกันกับเซลล์หกเหลี่ยม ใช้ใน wargames มากมาย และไม่เพียงแต่: นี่คือตัวอย่างวิธีการสร้างแผนที่การต่อสู้ Heroes of Might & Magic แบบดั้งเดิม

    การ์ดทั้งสองประเภทนี้เป็นการ์ดที่สืบทอดมาจากคลาสทั่วไป TLKITileMap.

  • กราโปวายา- TLKIGraphMap- การ์ดใบนี้มี พื้นหลัง (คุณสมบัติพื้นหลัง)และประเด็นสำคัญที่เน้นไว้คือวัตถุคงที่ ตำแหน่งของวัตถุอื่นๆ บนแผนที่นี้แสดงด้วยพิกัดธรรมดา (เช่น ยานอวกาศในอวกาศระหว่างดวงดาว) หรือโดยการอ้างอิงถึงวัตถุ (เรือลำเดียวกันในวงโคจรของดาวเคราะห์) เหล่านี้คือไพ่ Master of Orion, Arcanum (สากล) และอื่น ๆ
  • การเย็บปะติดปะต่อกัน- TLKIClusterMap- มันมีคุณสมบัติพื้นหลัง เช่น กราฟอันหนึ่ง และคุณสมบัติที่สอง - หน้ากากซึ่งกำหนดว่าจุดใดเป็นของภูมิภาคใดและทรัพย์สิน เส้นขอบซึ่งกำหนดความเชื่อมโยงระหว่าง "เศษเล็กเศษน้อย" นี่คือวิธีการจัดเรียงแผนที่ เช่น ในยุคกลาง: สงครามทั้งหมดหรือวิคตอเรีย

มันเป็นสิ่งสำคัญ:คลาสแผนที่ไม่ได้อธิบายไว้ในโมดูล LKI2dEngine แต่อธิบายไว้ใน LKI2dMap

มุมเอียง

แต่ถ้าคุณคิดว่าสิ่งนี้ทำให้ความสามารถของ LKI-Creator ในการแสดงแผนที่หมดลง แสดงว่าคุณคิดผิดมาก

สามารถนำเสนอแผนที่ได้ มุมมองด้านบนหรือ มีมิติเท่ากัน- มองมุมเป็นแนวตั้ง ตัวอย่างเช่น แผนที่ของ Civilization III หรือ Heroes of Might & Magic IV เป็นแบบสามมิติ แต่ Civilization I ใช้มุมมองจากบนลงล่าง

โดยทั่วไปแล้ว ไอโซเมตรีจะใช้สำหรับแผนที่แบบเรียงต่อกัน ในขณะที่แผนที่กราฟจะใช้ในมุมมองด้านบน เนื่องจากมาตราส่วนของแผนที่กราฟมักจะเล็กกว่า แต่มีข้อยกเว้น: ตัวอย่างเช่นใน Medieval: Total War จะมีแผนที่สามมิติแบบปะติดปะต่อกัน

คุณสมบัติแผนที่มีหน้าที่รับผิดชอบต่อความมีมิติเท่ากัน คือมีมิติเท่ากันและพารามิเตอร์สองตัวที่กำหนดมุมที่กล้องของเรามอง: พี่และ ทีต้า.

ประการแรกมีหน้าที่รับผิดชอบในการหมุนของแผนที่โดยสัมพันธ์กับแกนตั้ง: ตัวอย่างเช่นหากคุณตั้งค่าเป็น 45 องศา (วัดเป็นองศา) เซลล์กริดสี่เหลี่ยมจะถูกวางแนวด้วยมุมขึ้นเช่นเดียวกับในอารยธรรม . ที่ Phi=0 ด้านใดด้านหนึ่งของเซลล์จะเป็นแนวนอน

ส่วนที่สองควบคุมการเอียงของกล้องโดยสัมพันธ์กับแนวตั้ง เพื่อความสะดวก จะแสดงเป็นอัตราส่วนของหน่วยความยาวแนวนอนและแนวตั้ง สมมติว่า ถ้าเราต้องการให้เซลล์ของเราถูกดึงให้สูงเพียงครึ่งหนึ่งของความกว้าง เราต้องตั้งค่าทีต้าเป็น 2

ด้วยแผนที่แบบเรียงต่อกัน เราไม่ได้รับอนุญาตให้เลือกมุมเหล่านี้โดยพลการ เพราะท้ายที่สุดแล้ว เรายังไม่มี (ยัง) มี 3 มิติ ขึ้นอยู่กับพารามิเตอร์ของกระเบื้องโดยตรง ตัวอย่างเช่น หากเรามีแกนรูปทรงเพชรที่มีมุมสูงขึ้น และแกนตั้งมีขนาดเป็นครึ่งหนึ่งของแกนนอน เราจะต้องตั้งค่าพารามิเตอร์ 45 และ 2

แต่แผนที่กราฟและการเย็บปะติดปะต่อกันให้สิทธิ์คุณในการกำหนดพารามิเตอร์เหล่านี้ตามที่คุณต้องการ (และหากต้องการให้เปลี่ยนในกระบวนการ) แต่คุณไม่ควรดำเนินการกับสิ่งนี้ - นอกเหนือจากข้อเท็จจริงที่ว่าการเลี้ยวดังกล่าวต้องใช้เวลา หลายครั้งพวกเขาก็ดูไม่เจ๋งนัก และอย่าลืมว่าหากแผนที่ของคุณเป็นเชิงศิลปะ โดยมีรูปภาพ จารึก ฯลฯ แผนที่เหล่านั้นก็จะหมุนไปด้วย... โดยทั่วไป บางครั้งการวาดแผนที่แบบปะติดปะต่อกันจะง่ายกว่าโดยคำนึงถึงการหมุนที่ต้องการ - โชคดีที่ระยะทาง มักจะไม่มีบทบาทใดๆ ที่นั่น

ข้อต่อ

แผนที่แพชเวิร์ควิวด้านบน

แผนที่ไทล์มีปัญหาอื่น - การเชื่อมต่อไทล์ มันถูกควบคุมโดยพารามิเตอร์ TileBorderStyle- บ่อยที่สุดสิ่งนี้ กระเบื้องตรงซึ่งเป็นโหมดที่ไทล์เรียงชิดกันโดยไม่มีเอฟเฟกต์ขอบใดๆ หรือ ไทล์Borderซึ่งมีการวาดเส้นเพื่อแยกไทล์หนึ่งออกจากอีกไทล์หนึ่ง - ขอบเขตของเซลล์ (ในกรณีหลังอย่าลืมกำหนด สีโปรยในพารามิเตอร์ TileBorderColor).

แต่มีตัวเลือกที่ฉลาดกว่าเมื่อไทล์ที่เหมือนกันอยู่ติดกันโดยไม่มีการเปลี่ยนแปลงและมีการใช้ไทล์ที่แตกต่างกันโดยใช้ไทล์ "เฉพาะกาล" พิเศษ โดยปกติจะทำสิ่งนี้หากแผนที่ประกอบด้วยพื้นที่กว้างใหญ่ประเภทหนึ่งเป็นส่วนใหญ่ เช่น พื้นที่สีเขียวขนาดใหญ่ และแต่ละเซลล์ไม่สำคัญและผู้เล่นไม่ควรสังเกตเห็น นี่คือการ์ดเวทมนตร์ Heroes of Might แต่ถ้าแต่ละเซลล์ได้รับการประมวลผลแยกกันเช่นเดียวกับใน Civilization วิธีนี้ไม่เหมาะและควรแยกเซลล์ออกจากกันอย่างชัดเจนจะดีกว่า เทคโนโลยี “หลอมรวม” (หรือที่เรียกว่า หน้ากาก) ถูกระบุโดยค่า TileBorderStyle เท่ากับ ไทล์มาสก์- เราจะพูดถึงโครงสร้างของพวกเขาอีกครั้ง - นี่เป็นหัวข้อที่ค่อนข้างซับซ้อน

กระเบื้อง

องค์ประกอบแผนที่ - วัตถุคลาส ทีแอลคิไทล์- มีโครงสร้างที่เรียบง่าย ในตอนแรกประกอบด้วย: พิกัด สไปรท์ที่ดึงมัน รหัสประเภทไทล์ (ซึ่งกำหนดสิ่งที่เรามีที่นี่ - เนินเขา ทะเลทราย ถนน ทะเล) และความสามารถข้ามประเทศ (สิ่งนี้เกี่ยวข้องกับเกมส่วนใหญ่) อันสุดท้ายคือจำนวนหน่วยการเคลื่อนที่ที่ใช้ในการเคลื่อนที่ผ่านไทล์นี้ ที่ดินทีม. สำหรับแผ่นกระเบื้องที่ไม่สามารถใช้ได้ ค่านี้เป็นจำนวนลบ

พารามิเตอร์อื่น - วัตถุรายการออบเจ็กต์ที่อยู่ในไทล์นี้ (ประเภท TLKIGameObject)

หากต้องการทราบว่าเซลล์ใดถูกคลิก แผนที่มีวิธีการ เมาส์ไทล์(x,y) ส่งคืนไทล์ที่เลือก

วิธีการปูกระเบื้องได้แก่ เป็นเพื่อนบ้าน(กระเบื้อง, ระยะทาง) ฟังก์ชันนี้จะคืนค่าเป็นจริงถ้าไทล์อยู่ห่างจากไทล์ที่กำหนดไม่เกินเซลล์ระยะห่าง (โดยค่าเริ่มต้น พารามิเตอร์นี้จะเท่ากับ 1 นั่นคือ ถ้าคุณเพียงเขียน IsNeighbour(ไทล์) ฟังก์ชันจะส่งกลับค่าจริงสำหรับไทล์ที่อยู่ติดกันทันที ไปยังแผ่นกระเบื้องที่กำหนด สำหรับตารางสี่เหลี่ยม แผ่นกระเบื้องที่มีเส้นขอบแนวทแยงจะถือเป็น "เพื่อนบ้าน" ด้วย

ฟังก์ชั่น อันดับแรกเพื่อนบ้านและ ถัดไปเพื่อนบ้านใช้เพื่อตรวจสอบเซลล์ทั้งหมดที่อยู่ติดกับเซลล์ที่กำหนด เซลล์แรกชี้ไปที่เซลล์เพื่อนบ้านบางเซลล์ และเซลล์ที่สองสามารถเรียกได้หลังจากโทรหาเซลล์แรกเท่านั้น และจะแจกเพื่อนบ้านถัดไปทีละเซลล์

การแจงนับของเพื่อนบ้าน

// ทำให้เกิดความเสียหายต่อเซลล์

ขั้นตอน TObeliskTile.Damage (dmg: จำนวนเต็ม);

ถ้า(วัตถุนับ > 0) และ// เราอาจจะมี

// ไม่เกินหนึ่งวัตถุต่อเซลล์

(วัตถุ ID > 0) // วัตถุเฉื่อย

//ไม่เสียหาย

ธ.ค. (วัตถุ ฮิต

// ลบการป้องกันออกจากความเสียหายโดยอัตโนมัติ

สูงสุด(0,dmg-(วัตถุ เช่น TObeliskGameObject).การป้องกัน);

ถ้าวัตถุ โจมตีแล้วตาย; // เรากำจัดคนตาย

// การโจมตีด้วยลูกไฟ

ขั้นตอน TObeliskTile.ลูกไฟ;

varเพื่อนบ้าน: TObeliskTile;

เพื่อนบ้าน:= เพื่อนบ้านคนแรกเป็น TObeliskTile;

เพื่อนบ้านความเสียหาย(6);

เพื่อนบ้าน:= เพื่อนบ้านถัดไปเป็น TObeliskTile;

จนกระทั่งเพื่อนบ้าน = ไม่มี; // จนกว่าเพื่อนบ้านจะหมด

ตัวอย่างอยู่ในแถบด้านข้าง "การแจงนับเพื่อนบ้าน" ขั้นตอนนี้จะคำนวณลูกไฟที่กระทบเซลล์และเพื่อนบ้านทั้งหมด

นี่เป็นสิ่งที่น่าสนใจ: สำหรับงานของเธอ มันไม่สำคัญเลยเรามีโครงตาข่ายหกเหลี่ยมหรือสี่เหลี่ยมจัตุรัส

บ่อยครั้งที่เราต้องการพารามิเตอร์อื่นๆ และโดยปกติแล้วจะเป็นคลาสของไทล์ที่ประกอบเป็นแผนที่ - ลูกหลานทีแอลคิไทล์. ดังนั้นในตัวอย่าง - TObeliskTile ได้รับการสืบทอดมาจาก TLKITile

มันเป็นสิ่งสำคัญ:หากเรานำแผนที่แบบเรียงต่อกันมาสู่หน้าจอเกม พิกัด ตลอดจนวิธี TLKIGameObject ที่เกี่ยวข้องกับระยะทาง โดยค่าเริ่มต้นจะเริ่มการวัดระยะทางในรูปแบบไทล์แทนที่จะเป็นจุด พิกัดของปุ่ม ไอคอน ฯลฯ ยังคงวัดกันเป็นพิกเซล! แต่โหมดนี้สามารถปิดได้ - ซึ่งจะมีประโยชน์สำหรับกลยุทธ์แบบเรียลไทม์

การเลือกการ์ด

ดังนั้น เรามาเริ่มกันด้วยโครงตาข่ายสี่เหลี่ยม (TLKIRectMap) การทำแผนที่สามมิติ (พารามิเตอร์เชิงมุม 0, 1.5) ปล่อยให้ตารางถูกวาด (สไตล์tileBorder) แจ้งให้เครื่องยนต์ทราบว่าควรแสดงแผนที่นี้โดยเฉพาะ จนถึงตอนนี้ การดำเนินการที่จำเป็นทั้งหมดได้เสร็จสิ้นลงแล้วโดยไม่ต้องเขียนโค้ดแม้แต่บรรทัดเดียว

การดำเนินการเหล่านี้จะต้องเสร็จสิ้น ก่อนการเริ่มต้นกลไกรวมถึงการประกาศแบบอักษร

เราจะประกาศตัวเลขเหมือนเมื่อก่อนเป็นสไปรท์

เครื่องมือแก้ไขแผนที่

แผนที่แพชเวิร์ค, มีสามมิติ .

มีปัญหาค่อนข้างน้อยที่นี่ เอ็นจิ้นเดียวกันทุกประการ การประกาศไทล์เดียวกัน... อินเทอร์เฟซ เช่น การเลือกไทล์ การโหลด/บันทึก ฯลฯ สามารถทำได้อย่างง่ายดาย วิธีการมาตรฐาน Delphi: ไม่มีใครบังคับให้เราเปลี่ยนไปใช้โหมดเต็มหน้าจอ เราจะไม่วิเคราะห์สิ่งนี้ที่นี่ - ทุกอย่างอยู่ในไฟล์ตัวอย่าง ตัวอย่างโค้ดที่จงใจนำไปใช้ วิธีที่ง่ายที่สุด- หากต้องการ คุณสามารถสร้างกราฟิกจานสีออบเจ็กต์และจานสีไทล์ได้

ตัวแก้ไขมีเพียงสองคุณสมบัติที่ไม่คุ้นเคยสำหรับเรา อันแรกนั้นค่อนข้างง่าย: มันคือ คุณลักษณะใหม่เมาส์ที่ออกแบบมาสำหรับแผนที่แบบเรียงต่อกันโดยเฉพาะ การทำงาน TLKIRectMap.SelectTileส่งคืนตัวชี้ไปยังไทล์ที่แน่นอนที่ถูกคลิก เพื่อให้เราสามารถจัดการกับการคลิกได้อย่างง่ายดาย

แต่ผลิตภัณฑ์ใหม่ตัวที่สองสมควรได้รับการพิจารณาอย่างรอบคอบมากขึ้น

จริงๆ แล้ว มีหลายวิธีในการบันทึกข้อมูลและอ่านข้อมูลจากข้อมูลดังกล่าว เราเลือกวิธีการเข้ารหัสในไฟล์ แคนนอนเบส- Cannon เป็นเครื่องมือสำหรับอ่านและเขียนวัตถุที่สืบทอด TCannonObjectพร้อมการตรวจสอบประเภทและคุณสมบัติอื่นๆ

ลองดูโค้ด (“เขียนการ์ด”)

การบันทึกการ์ด

ขั้นตอน TObeliskMap.Save;

varฉัน,j: จำนวนเต็ม;

เริ่มต้นบันทึก(FName);

WriteStr(ชื่อแผนที่);

เขียน(Map.Width, SizeOf(Map.Width));

เขียน(Map.Height, SizeOf(Map.Height));

สำหรับฉัน:=0 ถึงแผนที่.กว้าง-1 ทำ

สำหรับเจ:=0 ถึงแผนที่ความสูง-1 ทำ

เขียน (Map.Tiles.Code, SizeOf (จำนวนเต็ม);

นี่คือวิธีการทำงาน ขั้นแรกคุณต้องเปิดไฟล์โดยใช้ขั้นตอนพิเศษ เริ่มต้นบันทึกซึ่งมีพารามิเตอร์เพียงชื่อไฟล์เท่านั้น จากนั้นเราจะบันทึกส่วนหัวสำหรับการควบคุมประเภทโดยใช้ขั้นตอนพิเศษ เขียนHeader- จากนั้นเราจะเขียนทุกสิ่งที่เราต้องการโดยใช้ขั้นตอนนี้ เขียนStrสำหรับสตริงและสำหรับฟิลด์อื่นๆ ทั้งหมด - เขียน(พารามิเตอร์ตัวที่สองคือขนาดของข้อมูลที่เขียนเป็นไบต์) คุณสามารถเขียนขั้นตอนของคุณเองสำหรับฟิลด์อ็อบเจ็กต์ได้ตามต้องการ บันทึกด้วยบันทึกส่วนหัว สุดท้ายเราก็ปิดไฟล์ตามขั้นตอน ฟินเซฟ.

ออบเจ็กต์ทั้งหมดที่มีส่วนหัวของตัวเองจะต้องประกาศแยกกัน ในบทที่ การเริ่มต้นโมดูล (ส่วนเสริมที่ตามมาทีหลัง การนำไปปฏิบัติซึ่งมีคำสั่งที่ต้องดำเนินการตั้งแต่เริ่มต้นเมื่อเริ่มต้นโปรแกรม) คุณควรเขียนบรรทัดต่อไปนี้ตัวอย่างเช่น:

ลงทะเบียนชื่อผู้ใช้(tpMap, "TObeliskMap");

ทีพีแมปเป็นค่าคงที่ที่คุณต้องประกาศด้วย เท่ากับ 1 และในตัวสร้างของวัตถุ TObeliskMap ให้กำหนดค่าของค่าคงที่นี้ให้กับพารามิเตอร์ ประเภท ID.

ทำไมยุ่งยากทั้งหมดนี้? นอกจากการจับคู่ประเภทแล้ว คุณยังได้รับสิทธิประโยชน์ที่สำคัญอีกประการหนึ่งอีกด้วย

หากรูปแบบไฟล์เปลี่ยนแปลง เช่น เนื่องจากมีการเพิ่มฟิลด์ใหม่ คุณไม่จำเป็นต้องเขียน "ตัวแปลง" ใด ๆ ที่แปลงไฟล์เก่าเป็นไฟล์ใหม่ รหัสของคุณจะอ่านโดยอัตโนมัติ

รหัสนี้จะเริ่มต้นฟิลด์ใหม่ให้ว่างเปล่าโดยอัตโนมัติหากไม่ได้บันทึกลงในไฟล์ และคุณสามารถเขียนไฟล์ได้โดยการเพิ่มบรรทัด WriteStr(Name) ที่ส่วนท้ายสุด

ความคิดเห็น:หากคุณยังไม่เข้าใจว่ากระบวนการนี้มีไว้เพื่ออะไร ไม่ต้องกังวล คุณสามารถใช้วิธีการบันทึกและบันทึกแบบเดิมๆ ได้ แต่ในโครงการเกมขนาดใหญ่อย่างแท้จริง เส้นทางนี้ให้ข้อได้เปรียบที่สำคัญ

มาเล่นกัน

ก่อนอื่นเราต้องสร้าง ชั้นเรียนใหม่มาจาก TLKIGameObject เราจะคิดถึงคุณสมบัติของตัวเก่า ในคลาสใหม่ คุณต้องเพิ่มฟิลด์สำหรับคุณลักษณะพื้นฐาน: ช่วง การเคลื่อนไหว และอื่นๆ

มันเป็นสิ่งสำคัญ:พารามิเตอร์ความเร็วเดิมของเรายังคงอยู่ แต่มันระบุความเร็วของชิ้นส่วนที่เคลื่อนที่ผ่านหน้าจอ ไม่ใช่ระยะทางที่จะเคลื่อนที่ต่อเทิร์น หากเรากำลังสร้างกลยุทธ์แบบเรียลไทม์ เราจะไม่จำเป็นต้องมีพารามิเตอร์ใหม่ แต่มิฉะนั้น เราจะต้องแนะนำพารามิเตอร์นั้น

บนหน้าจอของเรา เราจะใช้ปุ่ม TLKIButton ในรูปแบบของนักธนู นักดาบ นักมายากล ผี อัศวิน

ก่อนอื่นเรามีการจัดการ เรามากำหนดโซนตำแหน่งของด้านหนึ่งเป็น "เส้น" สามอันดับแรกของแผนที่ สำหรับอีกด้านหนึ่งเป็น "เส้น" สามด้านล่าง

รหัสทำงานเช่นนี้ เมื่อคุณกดปุ่มใด ๆ การติดตั้งเครื่องบินรบที่เกี่ยวข้องจะถูกเปิดใช้งาน การคลิกที่สี่เหลี่ยมว่างในพื้นที่ตำแหน่งจะเป็นการวางรูปนั้นไว้ตรงนั้นและปิดการใช้งานปุ่ม ทันทีที่ปุ่มทั้งหมดถูกปิดใช้งาน การเคลื่อนไหวจะถูกโอนไปยังศัตรู

เมื่อเริ่มต้นการเคลื่อนไหวใหม่แต่ละครั้ง ปุ่มทั้งหมดจะเปิดขึ้นอีกครั้ง ซึ่งทำเพื่อให้บุคคลสังเกตเห็นได้ง่ายขึ้นว่าเขายังไม่ได้มีลักษณะเหมือนใคร ดังนั้นการคลิกที่ปุ่มจะเป็นการเลือกรูปและทันทีที่มีการเคลื่อนไหวปุ่มก็จะหายไป อีกปุ่มหนึ่ง - “จบเทิร์น” - จะปรากฏหลังจากระยะการวางตำแหน่งเท่านั้น

ครั้งสุดท้ายที่เราดำเนินการเพื่อเปิดใช้งานและปิดใช้งานองค์ประกอบอินเทอร์เฟซ ดังนั้นเราจะไม่วิเคราะห์การดำเนินการนี้โดยละเอียด - ดูโค้ดตัวอย่าง

การเคลื่อนไหวของร่าง

// หากศัตรูครอบครองเซลล์ที่เลือกเราจะโจมตี

// ถ้าว่างเราก็ย้ายไปไหนถ้ายุ่งกับเรื่องของตัวเอง

// หรือสิ่งกีดขวาง - ไม่ต้องสนใจการคลิก

ไทล์:= Map.MouseTile(MouseX, MouseY);

ถ้า(ไทล์= ไม่มี)// คลิกนอกหน้าต่างเกม

แล้วออก;

// การย้าย

ถ้า(Tile.Objects.Count = 0)

และ(แยก(ตนเอง)

และไม่ย้ายแล้ว แล้ว

// มาดูกันว่าเราจะไปถึงที่นั่นได้ไหม

ถ้า ไม่ฮาสเวย์(ไทล์) แล้วออก;

MoveObj(ID, Tile.x, Tile.y);

// เกมดังกล่าวเป็นแบบผลัดตาเดิน - เคลื่อนที่ได้ทันที

ย้ายแล้ว:= true;

//

ถ้าถูกโจมตี แล้ว

ไอคอนมองเห็นได้:= เท็จ;

// จู่โจม

ถ้า(ไทล์.วัตถุ.นับ > 0)

และ(แยก(ตนเอง)

และไม่ถูกโจมตี แล้ว

วัตถุ:= Tile.Objects;

// เราโจมตีศัตรูเท่านั้น

ถ้า Obj.Side = ด้านข้าง แล้วออก;

Obj.ความเสียหาย(dmg);

โจมตี:= จริง;

// หากการย้ายเสร็จสมบูรณ์ ให้ลบไอคอนออก

ถ้าย้ายแล้ว แล้ว

ไอคอนมองเห็นได้:= เท็จ;

การเคลื่อนไหวได้รับการประมวลผลดังต่อไปนี้ (ดู "การย้ายชิ้นส่วน") เซลล์ที่ถูกคลิกตั้งอยู่ หากมีศัตรูอยู่บนนั้น และพวกมันอยู่ในระยะ เขาจะได้รับอันตราย ถ้ามันว่างเปล่าและอยู่ในระยะ ชิ้นส่วนจะเคลื่อนที่ (หากมีสิ่งกีดขวาง) หากถูกครอบครอง แต่ไม่ใช่โดยศัตรู การคลิกจะถูกเพิกเฉย .

เมื่อทั้งสองฝ่ายเข้ามาใกล้ มังกรก็ลงมือทำ พวกมันทำงานง่ายมาก: พวกเขาเลือกมังกรที่ไม่ใช่มังกรที่ใกล้ที่สุดซึ่งอยู่ภายในระยะ 7 ช่องจากพวกมันแล้วโจมตี ดูโค้ด Dragon Actions

การกระทำของมังกร

// ตรวจสอบกระเบื้องภายใน 7 ช่องมังกร

สำหรับผม:= สูงสุด(0, x - 7) ถึงต่ำสุด(ขนาดสูงสุด, x + 7) ทำ

สำหรับเจ:= สูงสุด(0, y - 7) ถึงต่ำสุด(ขนาดสูงสุด, y + 7) ทำ

ถ้า (Map.Tiles.Objects.Count > 0) และ

(Map.Tiles.Objects.Code>1)

// 0 - รหัสอุปสรรค 1 - มังกร

แล้ว เริ่ม

// การเลือกจุดที่จะย้าย

ถ้า x=ฉัน แล้วขวาน:=i

อื่นถ้า x>ฉัน แล้วขวาน:=i+2

อื่นขวาน:= i-2;

ถ้าย=เจ แล้วเอ๋:= เจ

อื่นถ้าคุณ>เจ แล้วใช่:= j+2

อื่นใช่:= j-2;

MoveObj(ไม่ใช่, ขวาน, ใช่);

// มาโจมตีกันเถอะ

แผนที่.กระเบื้อง.ความเสียหาย(12);

// ทำลายวงจร: ไม่เกินหนึ่งการโจมตี

//มังกรตัวละรอบ

สุดท้าย สิ่งที่เหลืออยู่คือการตรวจสอบว่ามากกว่าครึ่งหนึ่งของเสาโอเบลิสก์ถูกกองทหารฝ่ายหนึ่งยึดครองหรือไม่ และหากเป็นเช่นนั้น ให้หยุดเกมและประกาศผู้ชนะ!


ดังนั้นเราจึงมีเกมกลยุทธ์ อย่างไรก็ตามเพื่อความสุขที่สมบูรณ์สิ่งที่ขาดหายไปอย่างแรกเลยคือปัญญาประดิษฐ์ซึ่งจะทำให้เกมมีโหมดผู้เล่นคนเดียว ( ขั้นตอนที่ง่ายที่สุดเราไม่นับการควบคุมมังกร) นั่นคือสิ่งที่เราจะทำในครั้งต่อไป เจอกันอีกเดือน!

ในประเด็นต่อไป

เราจะพูดถึงประเด็นต่อไปนี้:

  • ระบบอนุภาคสำหรับแสดงควัน ประกายไฟ ฯลฯ
  • ทำงานด้วยความโปร่งใส
  • เครื่องยนต์สามมิติ
  • พื้นฐานเอไอ;
  • การดีบักโปรแกรม
  • การสร้างแผนเกมและสคริปต์
  • การเขียนเอกสารการออกแบบ
  • ความสมดุลของเกม
  • คิดผ่านตัวละครในเกมและแนวของพวกเขา
  • การทำงานกับแพ็คเกจ Photoshop และ 3D
  • แอนิเมชั่น;
  • ดนตรีและการพากย์เสียง
  • และอีกมากมาย

ค่อนข้างเป็นไปได้ที่จะเรียนรู้วิธีทำทั้งหมดนี้ด้วยมือของคุณเอง คุณจะเห็นสิ่งนี้ในไม่ช้า

เขียนถึงเรา...

สำหรับผู้ที่คิดว่าแพ็คเกจสามารถเสริมบางสิ่งได้ประการแรกอย่าลืมว่าไม่มี รุ่นสุดท้ายแพ็คเกจ แต่เป็นเพียงอันเดียวที่ใช้ฟังก์ชั่นที่อธิบายไว้ในบทความของเรา บางทีแนวคิดของคุณบางส่วนอาจถูกนำไปใช้แล้วและกำลังรออยู่ (ดูแถบด้านข้าง "ในประเด็นในอนาคต") และไม่ว่าในกรณีใด: เมื่อเสนอแนวคิดให้เรา พยายามหาเหตุผลว่าทำไมข้อเสนอของคุณจึงมีประโยชน์สำหรับหลาย ๆ เกมในคราวเดียว ไม่ใช่แค่สำหรับเกมเฉพาะของคุณเท่านั้น

สำหรับงานอิสระ

ในขณะที่รอฉบับต่อไป คุณสามารถทำงานในโครงการของคุณเองหรือลองปรับปรุงเรื่องนี้ก็ได้ ต่อไปนี้เป็นแนวคิดบางประการสำหรับการนำไปใช้งานของคุณเอง:

  • แบ่งวัตถุกีดขวางเป็นสิ่งที่ทำลายได้ (ต้นไม้และพุ่มไม้) และสิ่งที่ทำลายไม่ได้ (หิน) และตรวจสอบให้แน่ใจว่าลูกไฟและลมหายใจของมังกรเผาพืชพรรณ
  • สร้างหลุม (เซลล์สีน้ำตาล) หรือไฟที่ลุกไหม้หลายรอบ (เซลล์สีแดง) ณ สถานที่ที่เกิดการโจมตีด้วยไฟ
  • อนุญาตให้นักดาบและอัศวินปกป้องเพื่อนบ้านโดยมอบ +1 ให้กับการป้องกัน
  • ทำให้การเคลื่อนไหวของตัวเลขบนหน้าจอราบรื่น

แล้วถ้าเป็นเรียลไทม์ล่ะ?

การสร้างเกมวางแผนแบบเรียลไทม์ไม่ใช่เรื่องยากอีกต่อไป หากคุณเพียงแต่ให้วิธีการป้อนข้อมูลที่แตกต่างกันแก่ผู้เล่น วิธีที่ง่ายที่สุดในการทำเช่นนี้คือผ่านเครือข่าย - เราจะพูดถึงเรื่องนี้ในปัญหาที่กำลังจะเกิดขึ้น จำเป็นต้องมีการเปลี่ยนแปลงต่อไปนี้ด้วย:

  • ไม่จำเป็นต้องมีฟิลด์ ความเร็วของเกมที่ชั้นเรียน TObeliskObject- ใช้ความเร็วจากเครื่องยนต์พื้นฐาน (ความเร็วของการเคลื่อนที่ผ่านหน้าจอเท่ากับความเร็วของเกม)
  • การคำนวณระยะทางจำนวนเต็มถูกปิดใช้งาน
  • รหัสการเคลื่อนไหวของร่างถูกเขียนใหม่โดยคำนึงถึงความจริงที่ว่าจำเป็นต้องวาดวิถีรอบสิ่งกีดขวาง
  • ปุ่ม "สิ้นสุดการย้าย" จะถูกลบออก

นั่นคือทั้งหมดที่ คุณจะลองทำด้วยตัวเองไหม?

ฉันถือว่าบริษัทของคุณเป็นหนึ่งในบริษัทที่แข็งแกร่งที่สุดในตลาดบริการให้คำปรึกษาในประเทศของเรา ฉันชอบที่คุณพูดถึงปัญหาการจัดการที่หลากหลาย และครอบคลุมปัญหาเหล่านั้นด้วยคุณภาพและความลึกที่เพียงพอฉันพบข้อมูลที่เป็นประโยชน์มากมายในสิ่งพิมพ์ของบริษัทของคุณ เนื่องจากเป็นเรื่องน่าสนใจเสมอที่ได้ทำความคุ้นเคยกับประสบการณ์ของผู้เชี่ยวชาญและเรียนรู้จากพวกเขา

Borisyuk Yuri Aleksandrovich ที่ปรึกษาด้านการจัดการแพทย์ วิทยาศาสตร์เทคนิค

ฉันชอบชุดบทเรียนที่คุณสอนมากโดยส่วนตัวแล้วเมื่อก่อนเคยเป็นหัวหน้าโรงงาน ผมจึงเริ่มเปลี่ยนแนวทางการบริหารจัดการ ได้แก่ ขอขอบคุณข้อมูลที่ได้รับจากคุณ เธอตอบสนองต่อสิ่งที่ฉันทำและสังเกตเห็นที่โรงงาน ตั้งแต่นั้นมา ฉันเริ่มคิดว่าความสามารถทางอุตสาหกรรมของรัสเซียไม่มีประสิทธิภาพเพียงใด และมีศักยภาพมหาศาลเพียงใด และสิ่งนี้สามารถเกิดขึ้นได้อย่างไร ทำความรู้จักกับปัญหาเป็นการส่วนตัว สถานประกอบการที่แตกต่างกัน(บางทีเพื่อนก็ชวนผมเป็นผู้เชี่ยวชาญ) ผมเห็นว่าทำได้แค่ไหน จะเพิ่มทั้งประสิทธิผลและประสิทธิผลได้อย่างไร

ดรายจิน โอเล็ก โบริโซวิช

ใช่ ฉันชอบชั้นเรียนปริญญาโทของคุณแนวทางที่เป็นระบบความรู้เกี่ยวกับเนื้อหาในระดับสูงและแน่นอนว่ามีประสบการณ์เชิงปฏิบัติมากมายในประเด็นที่กำลังพิจารณา สิ่งที่ดึงดูดฉันก็คือสิ่งนั้นความเป็นมืออาชีพของ Alexander และความรู้ทางวิชาชีพในระดับสูงในเรื่องนี้ทำให้ฉันมองสิ่งที่คุ้นเคยอยู่แล้วแตกต่างออกไป จากมุมมองของฉันนี่คือการมองสิ่งที่คุณรู้ในรูปแบบใหม่ถือเป็นสิ่งสำคัญและจำเป็นมาก เพราะ... ในระหว่างการผ่าตัด ดวงตามักจะ “พร่ามัว” และคุณหยุดมองเห็นสิ่งที่ชัดเจนในความเป็นจริง

Elena Fedash ผู้อำนวยการฝ่ายทรัพยากรบุคคล ATB Corporation, Dnepropetrovsk