Post by u9 on Mar 24, 2008 19:50:36 GMT -5
I have been playing around with my little truck demo adding a house with perspective. The sad thing is that i have to use graphics.setline() to draw the sides of the houses because there is no way of drawing textured polygons (hint hint, wish-list). Anyway, i have found out that if the lines fall out side the screen area vertically, there is a huge slowdown in framerate. This does not happen if the lines are out side the screen horizontally.
Download my truck-demo and replace the code with this below. Then try and drive so the building exits the screen vertically compared to horizontally, while watching the FPS.
Maybe you can do something about it. I will of course fix my code to not call setline if it is outside the screen, but still might be a fix to be found somewhere in setline
Download my truck-demo and replace the code with this below. Then try and drive so the building exits the screen vertically compared to horizontally, while watching the FPS.
Maybe you can do something about it. I will of course fix my code to not call setline if it is outside the screen, but still might be a fix to be found somewhere in setline
' Simple truck and trailer simulation v. 2
' Done by u9 Mar 2008
' u9 AT kallnet D0T fo
Option Explicit
' Constants
Const WIDTH = 800
Const HEIGHT = 600
Const TILE_SIZE = 96
Const NUM_TRAILERS = 3
Const FILENAME = 0
Const WHEELBASE = 1
Const X_OFFSET = 2
Const Y_OFFSET = 3
Const IS_DEBUG = True
graphics.initialize WIDTH, HEIGHT, True
key.initialize
Dim font : font = graphics.createfont( "courier new", 12, True )
' Game data (vehicle informations)
ReDim VehicleData( NUM_TRAILERS, 3 )
VehicleData( 0, FILENAME ) = "gfx/truck.png"
VehicleData( 0, WHEELBASE ) = 38
VehicleData( 0, X_OFFSET ) = 10
VehicleData( 0, Y_OFFSET ) = 14
VehicleData( 1, FILENAME ) = "gfx/trailer_short.png"
VehicleData( 1, WHEELBASE ) = 21+21+1
VehicleData( 1, X_OFFSET ) = 13
VehicleData( 1, Y_OFFSET ) = 14
VehicleData( 2, FILENAME ) = "gfx/trailer_medium.png"
VehicleData( 2, WHEELBASE ) = 21+21+21-9
VehicleData( 2, X_OFFSET ) = 22
VehicleData( 2, Y_OFFSET ) = 14
VehicleData( 3, FILENAME ) = "gfx/trailer_long.png"
VehicleData( 3, WHEELBASE ) = 21+21+21+21-17
VehicleData( 3, X_OFFSET ) = 30
VehicleData( 3, Y_OFFSET ) = 14
ReDim vehicles( NUM_TRAILERS )
Dim i
For i = 0 To NUM_TRAILERS
Set vehicles(i) = New Vehicle
Dim image : image = graphics.loadimage( VehicleData(i,FILENAME) )
Call vehicles(i).Initialize( 8*TILE_SIZE+40*i, HEIGHT-60, pi/2, VehicleData(i,WHEELBASE), image, VehicleData(i,X_OFFSET), VehicleData(i,Y_OFFSET) )
Next
' Map data
Dim map
Set map = New LevelMap
Call map.Initialize( "map.ini" )
Dim viewport
Set viewport = New Point
' Test
Dim home
Set home = New House
Call home.Initialize( 10*TILE_SIZE, 6*TILE_SIZE, 2*TILE_SIZE, 2*TILE_SIZE, 150 )
Do While Not key.pressed( vk_escape ) And Not key.pressed( vk_windowx )
' Truck is vehicles(0)
Dim truck : Set truck = vehicles(0)
truck.turnAngle = truck.turnAngle * (0.95 - truck.speed/20)
If key.pressed( vk_left ) Then
truck.turnAngle = truck.turnAngle + 0.05
If truck.turnAngle > 1 Then truck.turnAngle = 1
End If
If key.pressed( vk_right ) Then
truck.turnAngle = truck.turnAngle - 0.05
If truck.turnAngle < -1 Then truck.turnAngle = -1
End If
' Move truck forward
If key.pressed( vk_up ) Then
truck.speed = truck.speed + 0.02
End If
' Move truck reverse
If key.pressed( vk_down ) Then
truck.speed = truck.speed - 0.008
End If
truck.speed = truck.speed * 0.99
Call MoveTruck( truck, truck.speed )
' Check if truck is picking up a trailer
If truck.attached Is nothing And abs( truck.speed ) < 0.1 Then
' Check distance to trailers
For i = 1 To NUM_TRAILERS
If GetDistance( vehicles(i).front.x - truck.rear.x, vehicles(i).front.y - truck.rear.y ) < 5 Then
Set truck.attached = vehicles(i)
Exit For
End If
Next
End If
If key.pressed( vk_space ) Then
Set truck.attached = nothing
End If
If Not truck.attached Is nothing Then
Call MoveTrailer( truck.attached, truck.rear )
Dim diff : diff = truck.angle - truck.attached.angle
If diff < -pi Then diff = diff + 2*pi
If diff > pi Then diff = diff - 2*pi
If abs( diff ) > 1.4 Then
Set truck.attached = nothing
End If
End If
graphics.clear
viewport.x = viewport.x * 0.97 + (truck.rear.x-WIDTH/2) * 0.03
viewport.y = viewport.y * 0.97 + (truck.rear.y-HEIGHT/2) * 0.03
viewport.x = min( max( viewport.x, 0 ), map.w * TILE_SIZE - WIDTH )
viewport.y = min( max( viewport.y, 0 ), map.h * TILE_SIZE - HEIGHT )
Call map.Draw( viewport )
For i = 0 To NUM_TRAILERS
Call DrawVehicle( vehicles(i), viewport )
Next
' Test
Call home.Draw( viewport )
If IS_DEBUG Then
Call DrawWheel( truck.front, truck.angle + truck.turnAngle, viewport )
Call DrawWheel( truck.rear, truck.angle, viewport )
For i = 1 To NUM_TRAILERS
Call graphics.setcircle( vehicles(i).front.x - viewport.x, vehicles(i).front.y - viewport.y, 2, argb(255,255,255,255 ) )
Call DrawWheel( vehicles(i).rear, vehicles(i).angle, viewport )
Next
End If
Call graphics.settext( "Use arrows to drive truck", 10, 10, font, argb(255, 255, 255, 255) )
Call graphics.settext( "Back to circle to pick up trailer", 10, 24, font, argb(255, 255, 255, 255) )
Call graphics.settext( "Hold space to release trailer", 10, 38, font, argb(255, 255, 255, 255) )
Call graphics.settext( "FPS: " & graphics.fps, WIDTH-80, 10, font, argb(255, 255, 255, 255) )
graphics.display
Call graphics.setfps( 60 )
Loop
' Draws the vehicle using it's image. Images are assumed to be rotated by +90 degrees, i.e. facing up
Sub DrawVehicle( truck, offset )
Call graphics.setangle( truck.image, truck.angle )
Call graphics.setxy( truck.image, truck.rear.x - truck.offset.x - int(offset.x), truck.rear.y - truck.offset.y - int(offset.y) )
Call graphics.setimage( truck.image )
End Sub
' Move truck along (s: speed)
Sub MoveTruck( t, s )
t.front.x = t.front.x + cos( t.angle + t.turnAngle ) * s
t.front.y = t.front.y - sin( t.angle + t.turnAngle ) * s
t.angle = GetDirection( t.front.x - t.rear.x, -(t.front.y - t.rear.y) )
t.rear.x = t.front.x - cos( t.angle ) * t.wheelBase
t.rear.y = t.front.y + sin( t.angle ) * t.wheelBase
End Sub
' Move trailer (t) to position (w)
Sub MoveTrailer( t, w )
t.front.x = w.x
t.front.y = w.y
t.angle = GetDirection( t.front.x - t.rear.x, -(t.front.y - t.rear.y) )
t.rear.x = t.front.x - cos( t.angle ) * t.wheelBase
t.rear.y = t.front.y + sin( t.angle ) * t.wheelBase
End Sub
' Draw a set of wheels
Sub DrawWheel( w, a, offset )
Dim ax, ay, bx, by
ax = w.x - cos(a) * 5 - int(offset.x)
ay = w.y + sin(a) * 5 - int(offset.y)
bx = w.x + cos(a) * 5 - int(offset.x)
by = w.y - sin(a) * 5 - int(offset.y)
Call graphics.setline( ax, ay, bx, by, argb(255,255,255,255) )
End Sub
' Get angle of a point from origo
Function GetDirection( x, y )
If x = 0 Then
If y > 0 Then
GetDirection = pi/2
Else
GetDirection = -pi/2
End If
ElseIf x > 0 Then
GetDirection = atn( y / x )
Else
GetDirection = atn( y / x ) + pi
End If
End Function
Function GetDistance( x, y )
GetDistance = sqr( x*x + y*y )
End Function
' Classes
class Point
Public x
Public y
End class
class Vehicle
Public front
Public rear
Public wheelBase
Public angle
Public turnAngle
Public image
Public offset ' Where is center of image
Public attached ' The object attached to this one (mostly for truck)
Public speed ' Also only used for truck
Public Sub Initialize( x, y, a, wb, i, xOff, yOff )
image = i
Set offset = New Point
offset.x = xOff
offset.y = yOff
Call graphics.SetCenter( image, offset.x, offset.y )
Me.wheelBase = wb
angle = a
turnAngle = 0
Set front = New Point
front.x = x + cos( a ) * Me.wheelBase
front.y = y - sin( a ) * Me.wheelBase
Set rear = New Point
rear.x = x
rear.y = y
speed = 0
Set attached = nothing
End Sub
End class
class LevelMap
Public map
Public w
Public h
Public tiles
Public Sub Initialize( file )
w = system.iniGetSetting( file, "Meta", "WIDTH" )
h = system.iniGetSetting( file, "Meta", "HEIGHT" )
Dim image : image = graphics.loadImage( system.iniGetSetting( file, "Meta", "IMAGE" ) )
Dim tileSize : tileSize = system.iniGetSetting( file, "Meta", "TILESIZE" )
Call MakeTiles( image, tileSize )
Call LoadMap()
End Sub
Private Sub MakeTiles( image, tileSize )
ReDim tiles( w * h )
Dim x, y, wTile, hTile
wTile = graphics.getwidth(image)/tileSize
hTile = graphics.getheight(image)/tileSize
For x = 0 To wTile - 1
For y = 0 To hTile-1
tiles(x*hTile+y) = graphics.createimage( tileSize, tileSize )
graphics.renderimage tiles(x*hTile+y)
Call graphics.CopyRegion( image, tiles(x*hTile+y), x*tileSize, y*tileSize, tileSize, tileSize, 0, 0 )
graphics.rendernormal
Call graphics.setscalexy( tiles(x*hTile+y), TILE_SIZE/tileSize, TIlE_SIZE/tileSize )
Next
Next
End Sub
Private Sub LoadMap()
ReDim map( w, h )
Dim row, col, string
For row = 0 To h-1
string = split( system.iniGetSetting( "map.ini", "Data", "Row_" & row ), "," )
For col = 0 To w-1
map(col,row) = string(col)
Next
Next
End Sub
Public Sub Draw( offset )
Dim part, remainder
Set part = New Point
Set remainder = New Point
part.x = int( int(offset.x) / TILE_SIZE )
part.y = int( int(offset.y) / TILE_SIZE )
remainder.x = int(offset.x) Mod TILE_SIZE
remainder.y = int(offset.y) Mod TILE_SIZE
Dim x, y
For x = 0 To int( ( WIDTH + TILE_SIZE )/TILE_SIZE )
For y = 0 To int( ( HEIGHT + TILE_SIZE )/TILE_SIZE )
'Call graphics.setxy( tiles( map(xPos+int(x),yPos+int(y)) ), x * TILE_SIZE, y * TILE_SIZE )
'Call graphics.setimage( tiles(map(xPos+int(x),yPos+int(y))) )
Call graphics.setxy( tiles( map(part.x+x,part.y+y) ), x*TILE_SIZE - remainder.x, y * TILE_SIZE - remainder.y )
Call graphics.setimage( tiles( map(part.x+x,part.y+y) ) )
Next
Next
End Sub
End class
class House
Private xPos
Private yPos
Private w
Private h
Private z
Public Sub Initialize( x, y, width, height, tall )
xPos = x
yPos = y
w = width
h = height
z = tall
End Sub
Public Sub Draw( offset )
' Calculate how far off center the top of the house should be
Dim x, y, x1, y1, ww, hh
x1 = int( ( xPos - int(offset.x) - WIDTH/2 ) * (1+z/1000) + WIDTH/2 )
y1 = int( ( yPos - int(offset.y) - HEIGHT/2 ) * (1+z/1000) + HEIGHT/2 )
ww = int( ( xPos + w - int(offset.x) - WIDTH/2 ) * (1+z/1000) + WIDTH/2 - x1 )
hh = int( ( yPos + h - int(offset.y) - HEIGHT/2 ) * (1+z/1000) + HEIGHT/2 - y1 )
x = xPos - int(offset.x)
y = yPos - int(offset.y)
Call graphics.setrect( x1, y1, ww, hh, argb( 255,255,255,255 ) )
' This needs to be "textured"
' Drawing walls
If x1 > x Then
Dim i, t, tmp1, tmp2
For i = x To x1
t = (i-x)/(x1-x) ' How far along line are we (from 0 to 1)
tmp1 = y*(1-t) + t*(y1)
tmp2 = (y+h)*(1-t) + t*(y1+hh)
Call graphics.setline( i, tmp1, i, tmp2, argb(255,155,155,155) )
Next
End If
If x1+ww < x+w Then
For i = x+w To x1+ww Step -1
t = (i-x-w)/(x1+ww-x-w)
tmp1 = y*(1-t) + t*(y1)
tmp2 = (y+h)*(1-t) + t*(y1+hh)
Call graphics.setline( i, tmp1, i, tmp2, argb(255,155,155,155) )
Next
End If
If y1 > y Then
For i = y To y1
t = (i-y)/(y1-y)
tmp1 = x*(1-t) + t*(x1)
tmp2 = (x+w)*(1-t) + t*(x1+ww)
Call graphics.setline( tmp1, i, tmp2, i, argb(255,155,155,155) )
Next
End If
If y1+hh < y+h Then
For i = y+h To y1+hh Step -1
t = (i-y-h)/(y1+hh-y-h)
tmp1 = x*(1-t) + t*(x1)
tmp2 = (x+w)*(1-t) + t*(x1+ww)
Call graphics.setline( tmp1, i, tmp2, i, argb(255,155,155,155) )
Next
End If
' Corners
Call graphics.setline( x1, y1, x, y, argb( 255,255,255,255 ) )
Call graphics.setline( x1+ww, y1, x+w, y, argb( 255,255,255,255 ) )
Call graphics.setline( x1, y1+hh, x, y+h, argb( 255,255,255,255 ) )
Call graphics.setline( x1+ww, y1+hh, x+w, y+h, argb( 255,255,255,255 ) )
End Sub
End class