แกล้งทำกราฟิกสามมิติในเกมอวกาศ 2 มิติ


15

ปิดครั้งแรกผมรู้ว่าสิ่งที่ปัญหาภาพวาดของฉันเป็นและฉันมีความคิดที่แตกต่างกันเกี่ยวกับวิธีการแก้มัน ฉันมาที่นี่เพื่อหาวิธีการปรับเฟรมที่ถูกวาดเพื่อให้ "ภาพลวงตา" มีมิติเท่ากันได้รับการดูแล

ฉันกำลังเขียนเกมดูนกแบบ 2 มิติที่เกิดขึ้นในอวกาศ ฉันกำลังพยายามใช้กราฟิกสามมิติในโลกที่อัพอยู่เหนือไม่มีโลกหมุนของเกมเหมือนในเกมไอโซโทปดั้งเดิม (โปรดจำไว้ว่าเกมเกิดขึ้นในอวกาศไม่มีภูมิประเทศ) นี่คือตัวอย่างสไปรต์ที่ฉันพยายามใช้: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64.pngหมุน 64 ครั้งเกี่ยวกับแกนตั้งของมันในมุมมอง 35 องศา (aka, ISO) ภาพถูกสร้างขึ้นดังนั้นสิ่งนี้สามารถเปลี่ยนแปลงได้

เพื่อความชัดเจนฉันได้บอกว่าทิศเหนือ (ขึ้น) คือ 0 องศาและทิศตะวันออก (ขวา) คือ 90

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

http://cell.stat-life.com/images/stories/AsteroidOutpost/ProjectIssue.png ด้านซ้ายฉันมีมุมมองด้านข้างทางขวาฉันมีมุมมองจากบนลงล่าง ด้านบนฉันมีมุมมองของยานอวกาศ / แผ่นสไปรต์ของโลก ที่ด้านล่างฉันมีสิ่งที่เทพดาดูเหมือนเมื่อวาดลงบนหน้าจอ

ที่ด้านบนขวาเป็นเวอร์ชั่นที่เรียบง่ายของวิธีการหมุนยานอวกาศของฉัน (แม้จะมีการแยกองศาระหว่างแต่ละเฟรม) ที่มุมล่างขวาคือมุมที่สไปรต์ดูเหมือนว่ากำลังหันหน้าไปเมื่อวาดมุมใดมุมหนึ่งบนหน้าจอ ปัญหานี้เกิดขึ้นอย่างชัดเจนที่สุดประมาณ 45 องศา นี่คือภาพที่วางซ้อนกับเส้น "ระนาบหน้าจอ" ซึ่งชี้ไปในทิศทางที่เรือควรหันเข้าหา: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLine.pngเส้นสีแดงควรเสมอจะชี้ไปในทิศทางเดียวกันกับเรือ แต่เป็นคุณสามารถมองเห็นปัญหาการฉายที่เป็นสาเหตุของปัญหา ฉันหวังว่าฉันจะอธิบายปัญหาได้ดีพอ

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

มันดูค่อนข้างแปลกเมื่อเรือลำนี้ยิงลำแสงเลเซอร์ไปที่เป้าหมายที่อยู่ด้านหนึ่งเมื่อมันควรจะยิงตรงไปข้างหน้า

ดังนั้น ... คำตอบที่ฉันได้มาคือ:

  1. หยุดพยายามปลอมมุมมองภาพวาดสามมิติไปใหญ่หรือกลับบ้าน หมุนโลกของฉันแล้ว (PS: นี่จะแก้ไขปัญหาของฉันใช่ไหม)
  2. เปลี่ยนแผ่นสไปรต์ของฉัน (อย่างใด) เพื่อให้มีเฟรมที่แสดงถึง "มุมหน้าจอ" ที่โมเดลจะถูกดู ดังนั้นเมื่อฉันขอภาพ 45 องศาจริง ๆ แล้วมันจะดูเหมือน 45 องศาบนหน้าจอ
  3. เปลี่ยนระบบการเรนเดอร์ของฉันเพื่อจับเฟรมอื่นจากแผ่นสไปรต์ (อย่างใด) โดยรู้ว่าการที่เฟรม "ปกติ" นั้นดูตลก ดังนั้นแทนที่จะคว้าเฟรม 45 องศามันจะคว้า ... 33 องศาเฟรม (แค่เดา) เพื่อให้มันดูถูกต้องสำหรับผู้ใช้
  4. เพียงแค่ใช้ 3D! มันง่ายกว่าผู้ชายมาก

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

สำหรับสอง:การใช้วิธีที่ 2 หรือ 3 ฉันจะปรับมุมอินพุทหรือเอาท์พุทได้อย่างไร ฉันไม่ใช่คนที่เก่งในเรื่องการฉาย 3 มิติและการฝึกอบรม 3 มิติ (ให้การฝึกอบรม 2D อย่างเดียว) และคณิตศาสตร์อะไรก็ตามที่อาจใช้เพื่อให้ได้ผลลัพธ์ตามที่ฉันต้องการ

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

แก้ไข:

ฉันรู้ว่าปัญหายากที่จะเห็นภาพด้วยภาพนิ่งดังนั้นฉันได้ปฏิบัติตาม Sprite Library Visual Tester ของฉันเพื่อแสดงปัญหา: http://cell.stat-life.com/downloads/SpriteLibVisualTest.zipต้องใช้XNA 4.0แอปพลิเคชันนี้คือ เพียงหมุนเทพดาและวาดเส้นจากจุดศูนย์กลางออกไปที่มุมเกมคิดว่าควรหันหน้าเข้าหาเรือ

แก้ไข 8 ก.ย.

ต่อจากย่อหน้าที่ "คิดออกมาดัง": แทนที่จะใช้การฉายภาพ (เพราะมันดูยาก) ฉันคิดว่าฉันสามารถเอาเวกเตอร์หน่วยหันหน้าไปทางทิศเหนือ (0x, 1y, 0z) ให้ใช้เมทริกซ์เพื่อหมุนมุม เทพดาหันหน้าไปทางจริงจากนั้นหมุนอีกครั้งจาก "ระนาบดู" ออกไปด้านนอก "ระนาบผี" รอบแกน X แล้ว ... แบน เวกเตอร์ (โดยพื้นฐานแล้วฉายกลับ) ไปยังระนาบการดูโดยใช้ X และ Y เท่านั้น (ไม่สนใจ Z) จากนั้นใช้เวกเตอร์แบนใหม่นั้นฉันสามารถกำหนดมุมของมันและใช้มันเพื่อ ... บางสิ่งบางอย่าง ฉันจะคิดเพิ่มเติมภายหลัง

แก้ไข ก.ย. 8 (2)

ฉันพยายามติดตามความคิดของฉันจากด้านบนด้วยความสำเร็จใช่ไหม ดังนั้น ... เพื่อให้ได้เส้นสีแดงดูเหมือนว่ามันจะออกมาจากยานอวกาศของฉัน (เพื่อทดสอบเท่านั้น) ฉันทำสิ่งต่อไปนี้:

Vector3 vect = new Vector3(0, 1, 0);
vect = Vector3.Transform(vect, Matrix.CreateRotationZ(rotation));
vect = Vector3.Transform(vect, Matrix.CreateRotationY((float)((Math.PI / 2) - MathHelper.ToRadians(AngleFromHorizon))));
Vector2 flattenedVect = new Vector2(vect.X, vect.Y);

float adjustedRotation = (float)(getAngle(flattenedVect.X, flattenedVect.Y));

rotationมุมของหน้าจออยู่ที่ไหนและadjustedRotationตอนนี้มุมของหน้าจออยู่บนระนาบสไปรต์ ฉันไม่รู้ว่าทำไมฉันต้องหมุน Y แทน X แต่อาจเป็นเรื่องเกี่ยวกับ 3D ที่ฉันไม่รู้

ดังนั้นตอนนี้ฉันมีข้อมูลเพิ่มเติม แต่ฉันจะใช้สิ่งนี้เพื่อเลือกเฟรมที่เหมาะสมได้อย่างไร บางทีแทนที่จะหมุนจากระนาบมุมมองไปที่ระนาบสไปรต์แล้วจึงฉายกลับมาฉันควรพยายามทำอย่างอื่นรอบ ๆ นี่คือสไปรท์ของฉันที่มีเส้นสีแดงที่ปรับแล้ว แต่สิ่งที่ฉันต้องการทำคือการปรับโมเดลไม่ใช่บรรทัด: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLineCorrected.png

แก้ไข 9 ก.ย.

Horay! มันได้รับการแก้ไข! ฉันจะอธิบายสิ่งที่ฉันทำเพื่อแก้ไข:

ฉันทำตามคำแนะนำของ eBusiness และ "squished" โดยระบบพิกัดโลก (หรือยืด ... ) นี่เป็นวิธีแก้ปัญหา # 1 แม้ว่าฉันจะอยู่ภายใต้การแสดงผลที่ฉันจะต้องหมุนระบบพิกัดโลกของฉันเกี่ยวกับระบบ coord ของหน้าจอ ไม่จริง! ขึ้นยัง + y และขวายัง + x ฉันปรับเปลี่ยนวิธีการ WorldToScreen และ ScreenToWorld ของฉันเพื่อแปลงระหว่างโลกและพิกัดหน้าจออย่างถูกต้อง วิธีการเหล่านี้อาจไม่เหมาะสม แต่นี่เป็นเพียงสองวิธีใน codebase ของฉันที่ต้องเปลี่ยน

public Vector2 ScreenToWorld(float x, float y)
{
    float deltaX = x - (size.Width / 2f);
    float deltaY = y - (size.Height / 2f);

    deltaX = deltaX * scaleFactor / (float)Math.Sqrt(3);
    deltaY = deltaY * scaleFactor;

    return new Vector2(focusWorldPoint.X + deltaX, focusWorldPoint.Y + deltaY);
}

public Vector2 WorldToScreen(float x, float y)
{
    float deltaX = x - focusWorldPoint.X;
    float deltaY = y - focusWorldPoint.Y;

    deltaX = deltaX / scaleFactor * (float)Math.Sqrt(3);
    deltaY = deltaY / scaleFactor;

    return new Vector2(size.Width / 2f + deltaX, size.Height / 2f + deltaY);
}

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


ขอแสดงความยินดี อย่าลืมที่จะกระตุ้นฉันเมื่อคุณมีสิ่งที่สามารถเล่นได้ฉันต้องการที่จะดูว่าสิ่งนี้จะไป
aaaaaaaaaaaa

@eBusiness ตามที่สัญญาไว้: cell.stat-life.com/images/stories/AsteroidOutpost/ … และ cell.stat-life.com/images/stories/AsteroidOutpost/AOOhNoes.png สังเกตว่าเรือดูเหมือนว่าจะมองหอคอยนั้นอย่างไร : D ขอบคุณ!
John McDonald

@eBusiness วิดีโอyoutube.com/watch?v=Q8pR9KDBsCoนอกจากนี้ยังมีลิงก์สำหรับดาวน์โหลดเนื่องจากคุณถาม
John McDonald

คำตอบ:


4

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

draw(object.image, object.x*sqrt(3), object.y)

หมายเหตุที่ไม่ตอบรับ:

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

1
ฉันคิดว่า ... สิ่งนี้สามารถแก้ไขได้ทุกอย่าง เป็นการแก้ไขที่ง่ายและฉันสามารถทิ้งแผ่นไว้คนเดียว ฉันจะลองทำสิ่งนี้โดยเร็วและแจ้งให้คุณทราบว่ามันเป็นอย่างไร เพื่อตอบบันทึกของคุณ: 1) ฉันใช้ 2D เพราะเป็นสิ่งที่ฉันคุ้นเคยและฉันกำลังสร้างชีตของฉันจากโมเดล 3 มิติ 2) ขอบควรคม แต่ภายในขอบแข็งฉันสามารถใช้ช่องอัลฟาเพื่อต่อต้านนามแฝงได้ 3) ฉันไม่ได้วางแผนที่จะจำลองมิติที่สาม (มาก) ส่วนใหญ่ฉันต้องการกราฟิก 2D ที่ไม่ได้เลื่อนจากบนลงล่างและอนุญาตให้คุณเห็นด้านข้างของสิ่งต่าง ๆ
John McDonald

5

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

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

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

แก้ไข:

ปัญหาของคุณคือภาพหน้าจอที่สร้างขึ้นไม่ใช่มุมมองภาพสามมิติ แต่เป็นมุมมองกล้อง 3D ทั่วไป

ป้อนคำอธิบายรูปภาพที่นี่

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

ภาพหน้าจอของยานอวกาศของคุณถูกสร้างขึ้นด้วยมุมมองกล้อง 3 มิติ นั่นเป็นเหตุผลว่าทำไมการยิงด้วยเลเซอร์จึงปิด เปรียบเทียบเส้นสีแดงใน 'isometric' และ 'เปอร์สเปคทีฟ'

เครื่องมือสร้างสไปรต์ของคุณควรใช้Matrix.CreateOrthographic ()แทนMatrix.CreatePerspective ()สำหรับเมทริกซ์การฉาย


เทพดาถูกสร้างขึ้นโดยใช้เครื่องมือ 3 มิติถึง 2 มิติที่ฉันกำลังพัฒนาดังนั้นปัญหาอาจอยู่ในเครื่องมือนั้นได้เป็นอย่างดี เครื่องมือโหลดแบบจำลอง 3 มิติจากนั้นเพื่อให้บรรลุ Spaceship64.png (ด้านบน) มันหมุนแบบจำลองโดย (360/64) = 5.625 องศาบันทึกว่าเป็นเฟรมแล้วหมุนอีกครั้งด้วยจำนวนเดียวกันจนกว่าจะมีทั้งหมด 64 เฟรม รหัสที่ใช้ในการเรนเดอร์โมเดลอยู่ที่นี่: code.google.com/p/sprite-maker/source/browse/trunk/XNAWindow/… การหมุนจะทำในคลาสอื่น ฉันคิดเช่นกันว่าวิธีแก้ปัญหาที่ 2 และ 3 เป็นสิ่งที่ตรงกันข้ามกันใช่ไหม?
John McDonald

แก้ไขคำตอบของฉัน ดูด้านบน.
สตีเฟ่น

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

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

1

ฉันคิดว่าสิ่งที่คุณได้รับที่นี่เป็นเพียงภาพวาดสามมิติ คุณพูดถูกแล้วการมองเห็นมีความแตกต่างระหว่าง 0deg และ 10deg มากกว่าระหว่าง 90deg และ 100deg . . แต่นั่นเป็นเพราะมีมิติเท่ากันภายในอัดแกนเดียว หากคุณไม่ต้องการรูปลักษณ์นั้นคุณไม่ต้องการมีมิติเท่ากัน

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

ตอนนี้หาวิธีที่จะทำให้ผู้ใช้ของคุณเข้าใจ . . นั่นเป็นอีกเรื่องหนึ่งโดยสิ้นเชิง


ฉันจะต้องหมุนแกนโลกเพื่อให้ภาพลวงตาไม่สมบูรณ์โดยใช้วิธีนี้ (วิธี # 1 ในคำถาม) หรือไม่
John McDonald

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

โดย "หมุนแกนโลก" ฉันหมายถึงหมุนโลกที่สัมพันธ์กับกล้อง 45 องศาเพื่อให้ "ทิศเหนือ" หันไปทางด้านบนขวาหรือซ้ายบนของหน้าจอในแนวทแยงมุมแทนที่จะเป็น "นอร์ ธ " ขึ้นตรง ไปทางด้านบนของหน้าจอ
John McDonald


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