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. |
