ใน Pong คุณจะคำนวณทิศทางของลูกบอลได้อย่างไรเมื่อมันกระดอนจากไม้พาย?


28

ฉันพยายามที่จะสรุปปัญหาของ Hello World-y ในการพัฒนาเกม ฉันได้สร้างเกม TicTacToe ใน XNA แล้วฉันเดาว่าขั้นตอนต่อไปจะเป็นโคลนการฝ่าวงล้อม

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


คำถาม: ฉันจะทราบได้อย่างไรว่าลูกบอลควรตีกลับอย่างไรเมื่อมันกระทบกับไม้พายที่ด้านล่างของหน้าจอ

ฉันคิดว่ามันจะเป็นเช่น:

  1. จับความเร็วและมุมจากลูกบอลที่เข้ามา
  2. ตรวจจับตำแหน่งที่สัมผัสกับแถบ (ซ้ายสุด, ขวาสุด, กึ่งกลาง) และตามที่ให้ความเร็วสูงขึ้นหากสัมผัสบริเวณด้านนอก
  3. นี่คือที่ฉันติดอยู่ ฮิฮิ.

ข้อมูลเชิงลึกใด ๆ ฉันรู้ว่านี่ไม่ใช่คำถามประเภทคำตอบที่ตรงไปตรงมา แต่ฉันแน่ใจว่ามันเป็นปัญหาที่ทุกคนเผชิญ

ฉันกำลังอ่านหนังสือLinear Algebraที่แนะนำบนเว็บไซต์นี้ แต่ฉันก็ยังไม่รู้ว่าควรสมัครที่นี่หรือไม่


เขียนพงษ์ก่อนที่จะฝ่าวงล้อมจากนั้นคุณสามารถส่งออกลูกบอล, ผนังและพายในชั้นเรียนและขยายพวกเขาเช่นที่พวกเขาทำงานกับอิฐและ powerups ประเภทต่างๆ นอกจากนี้ฉันจะพิจารณาพงษ์ง่ายกว่าการฝ่าวงล้อม
ไม่ระบุตัวตน

คำตอบ:


30

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

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

var relativeIntersectY = (paddle1Y+(PADDLEHEIGHT/2)) - intersectY;

ใช้ค่า Y กลางของไม้พายและลบจุดตัด Y ของลูกบอล ถ้าไม้พายมีความสูง 10 พิกเซลตัวเลขนี้จะอยู่ระหว่าง -5 ถึง 5 ฉันเรียกสิ่งนี้ว่า "การตัดกันแบบญาติ" เพราะมันอยู่ใน "พื้นที่พายเรือ" ตอนนี้การแยกของลูกบอลเมื่อเทียบกับกลางไม้พาย

var normalizedRelativeIntersectionY = (relativeIntersectY/(PADDLEHEIGHT/2));
var bounceAngle = normalizedRelativeIntersectionY * MAXBOUNCEANGLE;

ใช้จุดตัดสัมพัทธ์แล้วหารครึ่งความสูงของไม้พาย ทีนี้ตัวเลข -5 ถึง 5 ของเราคือทศนิยมจาก -1 ถึง 1; มันปกติ จากนั้นคูณด้วยมุมสูงสุดที่คุณต้องการให้ลูกบอลกระดอน ฉันตั้งค่าเป็น 5 * Pi / 12 เรเดียน (75 องศา)

ballVx = BALLSPEED*Math.cos(bounceAngle);
ballVy = BALLSPEED*-Math.sin(bounceAngle);

สุดท้ายคำนวณความเร็วลูกใหม่โดยใช้ตรีโกณมิติอย่างง่าย

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


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

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

เหตุผลที่ฉันทำเช่นนี้เพราะลดการคำนวณต่อเฟรมที่จำเป็น ทุกเฟรมคุณทำx += vx * time;และy += vy * time;เวลาเป็นเวลานับตั้งแต่เฟรมสุดท้ายเป็นมิลลิวินาที (ดังนั้นความเร็วจะเป็นพิกเซลต่อมิลลิวินาที)


เกี่ยวกับการใช้ความสามารถในการโค้งบอล:

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

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

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


นั่นคือสิ่งที่ฉันกำลังทำอยู่ ความเร็วที่เร็วขึ้นเมื่อกระทบกับขอบของแถบ ขอบคุณมากที่สละเวลาเขียนสิ่งนี้ ฉันมีปัญหาในการทำความเข้าใจบางสิ่งบางอย่างแม้ว่า; ตัวอย่างเช่นใน snipper แรกคือ 'intersectY' คืออะไร นอกจากนี้ 'paddle1Y' ความสูงของแถบถูกต้องหรือไม่

intersectY คือตำแหน่งของลูกบอลที่มันตัดกับไม้พาย ฉันทำการคำนวณที่ซับซ้อนซึ่งฉันไม่เข้าใจจริง ๆ ในตอนนี้ แต่จริงๆแล้วมันคือค่า Y ของลูกบอลในเวลาที่มันชนกัน paddle1Y คือค่า Y ของไม้พายจากด้านบนของหน้าจอ PADDLEHEIGHT คือความสูงของไม้พาย ("บาร์")
Ricket

สิ่งที่คุณจะต้องเพิ่มเพื่อให้ลูก "โค้ง" ตัวอย่างเช่นเมื่อลูกบอลกำลังตีไม้พายคุณจะย้ายไม้พายเพื่อสร้างเส้นโค้งของลูกบอล บางสิ่งเช่นนี้: en.wikipedia.org/wiki/Curve_ball
Zolomon

ดูการแก้ไขและแจ้งให้เราทราบสิ่งที่คุณคิด (ถ้าคุณต้องการข้อมูลเพิ่มเติมเกี่ยวกับบางสิ่งบางอย่างไม่ได้อะไร ฯลฯ )
Ricket

ขอบคุณ! คำตอบที่ยอดเยี่ยมฉันสงสัยอยู่เสมอว่าจะบรรลุผลนั้นได้อย่างไร!
Zolomon

8

นานมาแล้วที่ฉันได้ทำสิ่งนี้ แต่ฉันคิดว่าฉันมีสิทธิ์

เมื่อมีการชนกันที่สมบูรณ์แบบมุมของการสะท้อนจะเท่ากับมุมของการเกิดอุบัติเหตุ

คุณรู้ว่าปกติของไม้พายของคุณ (สันนิษฐานว่าเป็นพื้นผิวเรียบ): N คุณรู้ตำแหน่งเดิมของบอลของคุณ (ที่จุดเริ่มต้นของการประทับเวลา): P คุณรู้จักตำแหน่งใหม่ของบอล (ในตอนท้ายของการจับเวลา): P 'คุณรู้จุดชนของคุณ: C สมมติว่าคุณคำนวณว่าเซ็กเมนต์ P -> P' ผ่านการพายของคุณตำแหน่งที่สะท้อนใหม่ของคุณ (P '') จะเป็น:

P '+ 2 * (N * (P' dot -N))

นิพจน์ย่อย N * (P 'dot -N) คำนวณความลึกตามปกติของการชนของลูกบอลที่เคลื่อนที่ เครื่องหมายลบคือการแก้ไขความจริงที่เรากำลังตรวจสอบความลึกตรงข้ามกับทิศทางปกติ

P '+ 2 * ส่วนของนิพจน์ย่อยย้ายลูกบอลกลับไปเหนือระนาบการชน 2 เท่าของความลึกของการชน

หากคุณต้องการการชนที่น้อยกว่าสมบูรณ์แบบให้เปลี่ยนตัวคูณ 2 เป็น (1 + (1-k)) โดยที่ k คือสัมประสิทธิ์แรงเสียดทาน การชนที่สมบูรณ์แบบมีค่า ak เท่ากับ 0 ทำให้มุมการสะท้อนกลับเป็นมุมที่เข้ามา ค่า k เท่ากับ 1 ทำให้เกิดการชนที่ลูกจะอยู่บนพื้นผิวของระนาบการชน

เวกเตอร์ความเร็วใหม่ของคุณ, V '', ทิศทางจะเป็น P '' - C ปรับให้เป็นมาตรฐานและคูณด้วยความเร็วที่เข้ามาของคุณและขนาดความเร็วผลลัพธ์ของคุณจะเท่าเดิม แต่ในทิศทางใหม่ คุณสามารถลิงด้วยความเร็วนั้นได้โดยคูณมันด้วยสัมประสิทธิ์ l ที่อาจเพิ่มขึ้น (l> 1) หรือลดลง (l <1) ความเร็วที่ได้

เพื่อสรุป:

P '' = P '+ (1-k) * (N * (P dot -N)) V' '= l * V * ((P' '- C) / | P' '- C |)

โดยที่ k และ l เป็นค่าสัมประสิทธิ์ที่คุณเลือก


5

การสะท้อนนั้นสามารถทำได้ "ถูกต้อง" หรือ "ทำได้ง่าย"

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

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


ไม่ใช่วิธี "ง่าย" และ "ขวา" ที่อธิบายไว้ข้างต้นเป็นหลักเดียวกันหรือไม่?
Tom

พวกมันจะเหมือนกันทุกประการถ้ากำแพงอยู่ในแนวแกนหลัก หากกำแพงไม่ได้อยู่ตามแนวแกน X, Y และ Z ดังนั้นไม่เลยกำแพงทั้งสองนั้นต่างกันอย่างสิ้นเชิง
dash-tom-bang

5

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

  • แน่นอนเนื่องจากความเร็วของลูกบอลเพิ่มขึ้นในเวลาที่ฉันแก้ไขก่อน / หลัง x, y ขั้นตอนเพื่อให้การตรวจสอบการชนที่แม่นยำวนรอบผ่าน "stepX" และ "stepY" ทั้งหมดซึ่งคำนวณหารแต่ละส่วนประกอบความเร็วด้วยโมดูลัสของเวกเตอร์ โดยตำแหน่งลูกปัจจุบันและอนาคต

  • หากการปะทะกันกับไม้พายเกิดขึ้นฉันจะหารความเร็ว Y เป็น 20 "20" นี้เป็นค่าที่สะดวกที่สุดที่ฉันพบเพื่อให้ได้มุมที่เกิดขึ้นสูงสุดเมื่อลูกบอลกระทบกับด้านข้างของไม้พาย แต่คุณสามารถเปลี่ยนเป็นอะไรก็ได้ ความต้องการของคุณเพียงแค่เล่นกับค่าบางอย่างและเลือกที่ดีกว่าสำหรับคุณ ด้วยการหารสมมุติว่าความเร็ว 5 ซึ่งก็คือความเร็วเกมเริ่มต้นของฉันด้วยจำนวนนี้ (20) ฉันได้รับ "ปัจจัยการสะท้อนกลับ" ที่ 0.25 การคำนวณนี้ทำให้มุมของฉันค่อนข้างเป็นสัดส่วนเมื่อความเร็วเพิ่มขึ้นจนถึงค่าความเร็วสูงสุดซึ่งอาจเป็น 15 (ในกรณีนี้: 15/20 = 0.75) เมื่อพิจารณาว่าไม้พายของฉัน x, y coords อยู่กึ่งกลาง (x และ y แสดงถึงศูนย์กลางของไม้พาย) จากนั้นฉันคูณผลลัพธ์นี้ด้วยความแตกต่างระหว่างตำแหน่งลูกบอลและตำแหน่งไม้พาย ยิ่งความแตกต่าง ยิ่งใหญ่มุมที่ทำให้เกิด นอกจากนี้การใช้แผ่นพับแบบ midhandled คุณจะได้รับเครื่องหมายที่ถูกต้องสำหรับการเพิ่ม x ขึ้นอยู่กับด้านที่ลูกบอลกระทบโดยไม่ต้องกังวลกับการคำนวณจุดศูนย์กลาง ในรหัสปลอม:

สำหรับ n = 0 ถึงโมดูลัส

ถ้า collision_detected ดังนั้น speedX = - (speedY / 20) * (paddleX - ballX); speedY = -speedY;
ออกจาก; จบถ้า

...

x = x + stepX; y = y + stepY;

จบสิ้น

จำให้พยายามเก็บสิ่งที่ง่าย ๆ เสมอ ฉันหวังว่ามันจะช่วย!


4

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

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


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

สิ่งที่ชอบangle = 1 - 2 * (ball.x - paddle.left) / paddle.widthจะให้ตัวเลขระหว่าง 1 ถึง -1; สิ่งนี้ (คูณค่าที่ปรับแต่งสำหรับกลไกเกมของคุณ) คือความชันของเส้นสัมผัสที่จุดที่ลูกบอลชนกัน สะท้อนให้เห็นถึงเส้นนั้นมากกว่าแนวนอนอย่างเคร่งครัด

4

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

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


1
ฉันเห็นคำปราศรัยนั้นเช่นกันประเด็นของเขาคือว่านี่เป็นการตัดสินใจออกแบบไม่ใช่การตัดสินใจทางคณิตศาสตร์: "angle of incidence = angle of reflection" จะถูกต้อง แต่ทำเพื่อการเล่นที่อ่อนแอ ยิ่งไปกว่านั้นใน Pong และ Breakout ดั้งเดิมความเร็วเป็นหน้าที่ของจำนวนการชนของลูก / ไม้พายที่มี (ดังนั้นความเร็วจะเพิ่มขึ้นเมื่อเวลาผ่านไป) พวกเขายังลดขนาดของไม้พายหลังจากจำนวนการยิงที่แน่นอนด้วย ฉันจะหลีกเลี่ยงการปล่อยให้ลูกบอลพุ่งขึ้นแม้ว่าคุณจะออกจากไม้พายไปเรื่อย ๆ
Ian Schreiber

4

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

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

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

การเคลื่อนไหวของลูกบอลไปทางทิศทางซ้ายหรือขวาเมื่อถูกตีทำให้เชื่อได้มากขึ้น

หวังว่าคุณจะมีความคิดอย่างน้อยตรรกะที่ชาญฉลาดขอขอบคุณ


1

ลองจินตนาการว่าคุณคำนวณระยะห่างระหว่างจุดศูนย์กลางของไม้พายและจุดที่ลูก Y ตีและเรียกมัน dตีและเรียกมันว่า สมมติว่าdมีค่าเป็นบวกเมื่อลูกบอลพุ่งเหนือจุดศูนย์กลางของไม้พาย ตอนนี้คุณสามารถเพิ่มd * -0.1ความเร็ว Y ของลูกของคุณและมันจะเริ่มเปลี่ยนทิศทาง นี่คือตัวอย่างในจาวาสคริปต์ที่สามารถแปลได้อย่างง่ายดายใน c #!

var canvas = document.querySelector('canvas');
var resize = function () {
  canvas.width = innerWidth;
  canvas.height = innerHeight;
};
resize();
var ctx = canvas.getContext('2d');
var ball = {
  size: 3,
  x: 1,
  y: canvas.height/2,
  vx: 2,
  vy: 0
};
var paddle = {
  height: 40,
  width: 3,
  x: canvas.width/2,
  y: canvas.height/2
};
addEventListener('mousemove', function (e) {
  paddle.y = e.clientY - (paddle.height/2);
});
var loop = function () {
  resize();
  ball.x += ball.vx;
  ball.y += ball.vy;
  if (ball.x > canvas.width || ball.x < 0) ball.vx *= -1; // horiz wall hit
  if (ball.y > canvas.height || ball.y < 0) ball.vy *= -1; // vert wall hit
  if (ball.x >= paddle.x && ball.x <= paddle.x + paddle.width && ball.y >= paddle.y && ball.y <= paddle.y + paddle.height) {
    // paddle hit
    var paddleCenter = paddle.y + (paddle.height/2);
    var d = paddleCenter - ball.y;
    ball.vy += d * -0.1; // here's the trick
    ball.vx *= -1;
  }
  ctx.fillRect(ball.x,ball.y,ball.size,ball.size);
  ctx.fillRect(paddle.x,paddle.y,paddle.width,paddle.height);
  requestAnimationFrame(loop);
};
loop();
body {overflow: hidden; margin: 0}
canvas {width: 100vw; height: 100vh}
<canvas></canvas>


0

สิ่งนี้จะช่วย http://www-classes.usc.edu/engr/ee-s/477p/s00/pong.htmlคุณก็กลับ x และ y ขึ้นอยู่กับที่มันกระทบหน้าจอ ถ้ามันเพิ่มขึ้นและขึ้นไปถึงจุดสูงสุดมันจะกลับค่าความเร็ว y ในขณะที่รักษาความเร็วไว้


0

สวัสดีฉันเพิ่งพยายามทำเกมบอลและคิดวิธีแก้ปัญหาสำหรับเรื่องนี้ ดังนั้นสิ่งที่ฉันทำ: พายเคลื่อนไหวในขณะที่เรากำลังเล่นเกม ระบบพิกัดของฉันถูกปล่อยทิ้งไว้ตามเดิมจุดบนซ้ายของผืนผ้าใบคือ 0,0 ไม้พายเคลื่อนไหวในระบบพิกัดนี้ แกน x ชี้จากความกว้าง 0 ถึงผืนผ้าใบและแกน y ชี้ไปที่ความสูงผ้าใบถึง 0 ฉันสร้างไม้พายขนาด Fix 100 กว้างและสูง 20 จากนั้นฉันวาดวงกลมที่มีจินตนาการรอบ ๆ เมื่อลูกบอลกระทบกับใบพัดฉันจะคำนวณ Centrepoint ของใบพัด

double paddleCenter=Squash.paddle.getXpos()+Squash.paddle.getPaddleWidth()/2;

จากนั้นฉันก็ลบจุดศูนย์กลางออกจากตำแหน่งปัจจุบันของลูกด้วยวิธีนี้ระบบพิกัดจะอยู่ที่กึ่งกลางของไม้พาย ballCenter คือจุดที่ลูกบอลกระทบกับไม้พาย (- (paddlewidth + r) .. 0 .. (paddlewidth + r )) นี่คืออะไร แต่ rescaling จุดกดปุ่มบนไม้พาย

double x0 = ballCenterX-paddleCenter;

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

double y0 = -Math.sqrt(paddleRadius*paddleRadius-x0*x0);

คำนวณผลของสมการปกติของวงกลมที่กำหนดไว้รอบ ๆ พายด้วย radis paddleRadius f (x, y) = x ^ 2 + y ^ 2-r ^ 2

double normalX=2*x0;
double normalY=2*y0;

ปรับเวกเตอร์ N ให้เป็นมาตรฐานเพื่อให้ได้เวกเตอร์หน่วยสำหรับพื้นผิวปกติ

double normalizer=Math.sqrt(normalX*normalX + normalY*normalY);
normalX=normalX/normalizer;
normalY=normalY/normalizer;

ตอนนี้เรามีบรรทัดฐานพื้นผิวปกติ (หน่วย) สำหรับไม้พาย คำนวณทิศทางใหม่ด้วยบรรทัดฐานพื้นผิวเหล่านี้ซึ่งจะถูกคำนวณด้วยความช่วยเหลือของสูตรเวกเตอร์การสะท้อนกลับ: new_direction = old_direction-2 * จุด (N, old_direction) * N แต่แทนที่ด้วยการชี้ปกติของพื้นผิวขึ้นไปเสมอ จะเปลี่ยนจากจุดหนึ่งไปยังอีกจุดที่ลูกบอลกระทบไม้พาย

double eta=2; //this is the constant which gives now perfect reflection but with different normal vectors, for now this set to 2, to give perfect reflection
double dotprod=vX*normalX+vY*normalY;
vX=vX-eta*dotprod*normalX;//compute the reflection and get the new direction on the x direction
vY=-vY;//y direction is remain the same (but inverted), as we just want to have a change in the x direction

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

https://github.com/zoli333/BricksGame

เขียนด้วยภาษาจาวาด้วย eclipse มีวิธีแก้ไขปัญหาอื่นสำหรับความคิดเห็นนี้ใน Ball.java ที่การ rescaling ไม่เกิดขึ้นฉันไม่ย้ายระบบพิกัดพิกัดไปยังจุดศูนย์กลางของใบพัดแทนฉันคำนวณทั้งหมดข้างต้นจากระบบพิกัด 0,0 ที่ซับซ้อน จุดศูนย์กลางของไม้พาย งานนี้ยัง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.