Top down rotating racer viewports?
Monkey Forums/Monkey Beginners/Top down rotating racer viewports?
| ||
I noticed that Monkey X features viewports. I know it can provide both canvas and sprite rotation. Can I write a multi player game in monkey where each player gets their own viewport and the camera stays rotated the same angle as the car's direction for each one? I could do this manually with a ton of trig math recalculating and replacing each object and using sprite rotations but I'm hoping I can keep the world intact and simply rotate the camera in a top down perspective for each player so the car always seems to point north in the viewport. A crap car sprite my demo requires "viper.png" Strict Import mojo2 Class Car Field x:Float = DeviceWidth() / 2.0 Field y:Float = DeviceHeight() / 2.0 Field direction:Float = 0 Field speed:Float = 0 Field sprite:Image Field first_player:Bool Method New(_x:Float, _y:Float, _direction:Float, _first_player:Bool = True) x = _x y = _y direction = _direction speed = 0 Print "attempting to make new image" sprite = Image.Load("viper.png") Print "Loaded" first_player = _first_player End Method PollInputs:Void() Local kl:Int = KEY_LEFT Local kr:Int = KEY_RIGHT Local ku:Int = KEY_UP Local kd:Int = KEY_DOWN If Not first_player Then kl = KEY_A If Not first_player Then kr = KEY_D If Not first_player Then ku = KEY_W If Not first_player Then kd = KEY_S If KeyDown(kl) Then direction += 2 If KeyDown(kr) Then direction -= 2 If KeyDown(ku) Then speed += .1 If KeyDown(kd) Then speed -= .5 If speed > 4 Then speed = 4 If speed < -2 Then speed = -2 End Method Move:Void() PollInputs() x += Cos(direction) * speed y -= Sin(direction) * speed End End Class Test Extends App Field canvas:Canvas Field my_car:Car Field my_car2:Car Method OnCreate:Int() ' Initialize data here canvas=New Canvas() SetUpdateRate(60) my_car = New Car(DeviceWidth() / 2, DeviceHeight() / 2, 0) my_car2 = New Car(DeviceWidth() / 2 + 128, DeviceHeight() / 2, 0, False) Return 0 End Method DrawCar:Void() canvas.SetColor(0.0, 0.0, 1.0, 1.0) canvas.DrawImage(my_car.sprite, my_car.x, my_car.y, my_car.direction) canvas.SetColor(1.0, 0.0, 0.0, 1.0) canvas.DrawImage(my_car2.sprite, my_car2.x, my_car2.y, my_car2.direction) End Method DrawGrid:Void() Local x_divs:Float = 20 Local x_step:Float = DeviceWidth() / x_divs Local y_divs:Float = 15 Local y_step:Float = DeviceHeight() / y_divs canvas.SetColor(1, 0, 0, 1) For Local x:Int = 0 To x_divs - 1 canvas.DrawLine(x * x_step, 0, x * x_step, DeviceHeight()) Next canvas.SetColor(1, .5, 0, 1) For Local y:Int = 0 To y_divs - 1 canvas.DrawLine(0, y * y_step, DeviceWidth(), y * y_step) Next End Method OnUpdate:Int() ' Game logic here my_car.Move() Return 0 End Method OnRender:Int() canvas.Clear(0, 0, 0) DrawGrid() canvas.SetColor(1, 1, 1) DrawCar() canvas.Flush() Return 0 End End Function Main:Int() New Test Return 0 End |
| ||
You can just draw the world from each car's perspective in a separate window, using SetScissor() to define the drawn area. It will be no different from rendering a single car in its environment, except you do it twice. I'm not familiar with the viewport functionality, but it should be able to handle this. But even if it doesn't, you just have to rotate everything in the world around the car by the same amount. |
| ||
I need help with rotation now. The translation is working to emulate a centered camera in the code below. (Grab the car images from the initial post if you need them to run the code below) Well some time later I've managed to get a camera that follows a car around. What I need is the camera to stay focused on the car's position (as I've done below) but also rotate so the car always points north in the view. THAT is the part I need help with. I don't want to manually rotate the entire world around the car using trig. That is best left to the matrix operations of the canvas. Strict Import mojo2 Class Car Field x:Float = DeviceWidth() / 2.0 Field y:Float = DeviceHeight() / 2.0 Field direction:Float = 0 Field speed:Float = 0 Field sprite:Image Field first_player:Bool Method New(_x:Float, _y:Float, _direction:Float, _first_player:Bool = True) x = _x y = _y direction = _direction speed = 0 Print "attempting to make new image" sprite = Image.Load("viper.png") Print "Loaded" first_player = _first_player End Method PollInputs:Void() Local kl:Int = KEY_LEFT Local kr:Int = KEY_RIGHT Local ku:Int = KEY_UP Local kd:Int = KEY_DOWN If KeyDown(kl) Then direction += 2 If KeyDown(kr) Then direction -= 2 If KeyDown(ku) Then speed += .1 If KeyDown(kd) Then speed -= .5 If speed > 4 Then speed = 4 If speed < -2 Then speed = -2 End Method Move:Void() PollInputs() x += Cos(direction) * speed y -= Sin(direction) * speed End End Class Test Extends App Field canvas:Canvas Field my_car:Car Field my_car2:Car Method OnCreate:Int() ' Initialize data here canvas=New Canvas() SetUpdateRate(60) ' Two Car objects, we'll only be able to move car 1 my_car = New Car(DeviceWidth() / 2, DeviceHeight() / 2, 0) my_car2 = New Car(DeviceWidth() / 2 + 128, DeviceHeight() / 2, 0, False) Return 0 End Method DrawCar:Void() ' Draw both cars canvas.SetColor(0.0, 0.0, 1.0, 1.0) canvas.DrawImage(my_car.sprite, my_car.x, my_car.y, my_car.direction) canvas.SetColor(1.0, 0.0, 0.0, 1.0) canvas.DrawImage(my_car2.sprite, my_car2.x, my_car2.y, my_car2.direction) End Method DrawGrid:Void() ' Draw simple grid to help see car movment Local x_divs:Float = 20 Local x_step:Float = DeviceWidth() / x_divs Local y_divs:Float = 15 Local y_step:Float = DeviceHeight() / y_divs canvas.SetColor(1, 0, 0, 1) For Local x:Int = 0 To x_divs - 1 canvas.DrawLine(x * x_step, 0, x * x_step, DeviceHeight()) Next canvas.SetColor(1, .5, 0, 1) For Local y:Int = 0 To y_divs - 1 canvas.DrawLine(0, y * y_step, DeviceWidth(), y * y_step) Next End Method OnUpdate:Int() my_car.Move() Return 0 End Method OnRender:Int() 'Vars to position "camera" offsets Local half_width:Float = DeviceWidth() * .5 Local half_height:Float = DeviceHeight() * .5 Local pos_x:Float = (my_car.x - half_width) * -1 Local pos_y:Float = (my_car.y - half_height) * -1 'Move camera to car's center canvas.Clear(0, 0, 0) canvas.PushMatrix() canvas.Translate(pos_x, pos_y) DrawGrid() canvas.SetColor(1, 1, 1) DrawCar() canvas.PopMatrix() canvas.Flush() Return 0 End End Function Main:Int() New Test Return 0 End |
| ||
Rotate the world using matrix operations. Then draw the world but *not* the car. Then draw the car un-rotated (or rotated to face north or whatever, maybe you wiggle it slightly in the appropriate direction when it's turning.) |
| ||
From what i've seen ignitionX or Pyro sounds like the perfect solution to your problems :) maybe give it a try. |
| ||
Rotate the world using matrix operations. Then draw the world but *not* the car. Then draw the car un-rotated (or rotated to face north or whatever, maybe you wiggle it slightly in the appropriate direction when it's turning.) In order to draw the world correctly the center of the view needs to be positioned where the car is and rotated the cars direction + 90 degrees. From what i've seen ignitionX or Pyro sounds like the perfect solution to your problems :) maybe give it a try. Thanks for the advice but the solution to this problem just requires 3 - 5 or so lines of code to move to the car's position then rotate the world appropriately. It's a math problem that I'm working on more than needing additional functionality and bolting a framework on. I guess I'll just keep trying to get the math correct here. |
| ||
Sounds like you have it, just fiddle with the translations/rotations until it works. |