ฟังก์ชั่นสำหรับการเคลื่อนไหวของดวงอาทิตย์?


9

ดังนั้นเมื่อสไปรต์ดวงอาทิตย์ถูกวางที่ขอบฟ้า (x = 0, y = worldheight / 2) ฉันพยายามคิดฟังก์ชั่นเพื่อทำให้ดวงอาทิตย์ขึ้นแล้วตก

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

หากใช้ y = sin (x) ดังนั้น x จะต้องอยู่ในช่วงระหว่าง 0 ถึง pi สำหรับเส้นโค้งเต็มขณะที่มีความเร็วคงที่สำหรับ X

ความคิดหรือข้อเสนอแนะ?

แก้ไข: ขอบคุณครับ!

อาทิตย์ทำงาน!

คำตอบ:


7

เกี่ยวกับปัญหา 0 ถึง pi โดยทั่วไปสิ่งที่คุณต้องทำคือปรับขนาด X ตามตัวคูณ ตัวอย่าง:

y = sin(x * pi / worldWidth)

http://www.wolframalpha.com/input/?i=Plot%5BSin%5Bx%5D%2C+%7Bx%2C+0%2C+Pi%7D%5D

อย่างไรก็ตามนี่ไม่ใช่เส้นโค้งที่คุณอาจมองหา คุณควรใช้แบบฟอร์มพารามิเตอร์:

t = 0 -> pi over the course of a day
y = sin(t)   -> goes from 0 up to 1 at noon, then down to 0 again
x = (1-cos(t))/2 -> starts at 0 goes up to 1 by sundown.

http://www.wolframalpha.com/input/?i=ParametricPlot%5B%7B1+-+Cos%5Bt%5D%2C+Sin%5Bt%5D%7D%2C+%7Bt%2C+0%2C+Pi% 7D 5D%

การรวมกันของความบาปสำหรับ Y และ cos สำหรับ X นี้จะติดตามวงรี


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

12

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

ใช้เวลา

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

ต่างจากชีวิตจริงฉันจะแค่คิดว่าวันนั้นเริ่มต้นที่ 0 ชั่วโมงและกลางคืนเริ่มต้นที่ 12 ชั่วโมง นี่จะทำให้การคำนวณบางอย่างง่ายขึ้น

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

float hours = 0.0f;                       // From 0 to 24 wrapping around
const float HoursPerSecond = 1f / 120f;   // E.g. 2 minutes = 1 hour ingame

public void Update(float elapsed)
{
    hours += elapsed * HoursPerSecond;    // Advance clock
    if(hours >= 24f) hours -= 24f;        // Wrap around 24 hours
}

องค์ประกอบ

ตอนนี้ก่อนที่จะตั้งค่าการเคลื่อนไหวของดวงอาทิตย์ของเราเราต้องระบุพารามิเตอร์บางอย่าง โดยเฉพาะอย่างยิ่งที่ค่า X ใดที่เพิ่มขึ้นจากขอบฟ้าและที่ค่า X ใดที่ตกอยู่ในขอบฟ้า นอกจากนี้สิ่งที่ Y สอดคล้องกับเส้นขอบฟ้าและสิ่งที่เขาควรจะสูงกว่าเส้นนั้น

float startX = 0;
float endX = 1000;
float horizonY = worldHeight/2;
float amplitudeY = 200;

การคำนวณพิกัดของดวงอาทิตย์

ตอนนี้ถึงเวลาที่จะคำนวณตำแหน่งของดวงอาทิตย์ของเราตามเวลาที่กำหนดในแต่ละวัน ฉันจะใช้ฟังก์ชันพารามิเตอร์แบบเดียวกับที่จิมมี่ใช้ แต่มีโดเมนตั้งแต่ [0..2PI] แทน (เพื่อให้ดวงอาทิตย์กลับสู่ตำแหน่งเดิมในเวลารุ่งสาง):

x = (1-cos (t)) / 2

y = sin (t)

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

ขั้นตอนแรกคือการปรับจำนวนชั่วโมงจากช่วง [0..24) เป็นช่วงของฟังก์ชันของเราซึ่งคือ [0..2PI):

float t = (hours / 24f) * MathHelper.TwoPi;          // Scale: [0..24) to [0..2PI)

ต่อไปเราใช้ฟังก์ชั่นเพื่อรับค่าระหว่าง 0 และ 1 ที่ฉันพูดถึงข้างต้น:

float horizontal = (float)((1-Math.Cos(t)) / 2f);    // Changes: 0 1 0
float vertical = (float)(Math.Sin(t));               // Changes: 0 1 0 -1 0

และในที่สุดเราก็ปรับค่าเหล่านั้นโดยใช้พารามิเตอร์ของดวงอาทิตย์:

float sunX = startX + (endX - startX) * horizontal;    // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical;         // Up and down around horizonY

+1 ด้วยความอัศจรรย์ความเสียใจเพียงอย่างเดียวของฉันคือฉันไม่สามารถทำเครื่องหมายสองคำตอบ!
Ross

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