Ok. I got some of the collisions to work.
The collision works against the walls on the left, right, top and bottom side, but it's not quite right when it comes to the walls in the middle (it depends on the angle of the player), and I'm not sure how to fix it. Any suggestions?
And is this a good way of doing collision detection? So far it seems quite complicated (at least for a beginner like me). Is there a simpler solution and I'm just over-complicating it?
Here's the code. You don't need any media files to try it.
`Init stuff
set display mode 800,600,32
sync on
sync rate 0
hide mouse
`Load images
`load image "redplayer.png", 1
`load image "bluesquare.jpg", 1
`load image "smallred2.jpg", 2
`load image "greysquare.jpg", 99
`load image "brownsquare.jpg", 100
`Makes some images. Use this if no media is included
`Player image
box 0,0,32,32,rgb(200,0,0),rgb(225,225,225),rgb(200,0,0),rgb(225,225,225)
get image 1,0,0,31,31
`Checkbox image
box 0,0,32,32,rgb(0,0,200),rgb(0,0,200),rgb(0,0,200),rgb(0,0,200)
get image 2,0,0,5,5
`Floor image
box 0,0,32,32,rgb(150,150,150),rgb(200,200,200),rgb(150,150,150),rgb(150,150,150)
get image 99,0,0,32,32
`Wall image
box 0,0,32,32,rgb(50,50,50),rgb(100,100,100),rgb(50,50,50),rgb(50,50,50)
get image 100,0,0,32,32
`Some variables. The x and y variables for the player must be float or
`else the player movement will be wrong. I don't know why...
xsize = 24
ysize = 17
playerAngle# = 0
playerx# = 200
playery# = 500
`Some variables to control the speed of the player
speed = 6
ready = 1
t = timer()+speed
`Make an array to store the map data
dim map(xsize,ysize)
`Enter some data into the array
`Floor
for x = 0 to xsize
for y = 0 to ysize
map(x,y) = 99
next y
next x
`Walls
map(12,7)=100
map(12,8)=100
map(12,9)=100
map(10,7)=100
map(10,8)=100
map(10,9)=100
map(9,9)=100
map(13,9)=100
for i = 0 to xsize
map(i,ysize) = 100
map(i,0) = 100
next i
for i = 0 to ysize
map(xsize,i)=100
map(0,i)=100
next i
`Start Main Loop
`************************************************************************************************************************
do
`Clear the screen
cls
`Timer to control the speed of the player
if t < timer() then ready = 1
`Player movement and checks for collisions against walls
gosub player_movement
`Draw the sprites to the screen
gosub draw_sprites
`Draw the 4 "checkpoints" for the player collision. This is for only for testing.
sprite 2, frontLeftX, frontLeftY, 2
offset sprite 2,2,2
set sprite priority 2, 2
sprite 3, frontRightX, frontRightY, 2
offset sprite 3,2,2
set sprite priority 3, 2
sprite 4, backLeftX, backLeftY, 2
offset sprite 4,2,2
set sprite priority 4, 2
sprite 5, backRightX, backRightY, 2
offset sprite 5,2,2
set sprite priority 5, 2
`Draw some text to the screen. This is only for testing.
text 0, 0, "FPS: " + str$(screen fps())
`Display the value of the map array for each corner of the player. 99 = floor. 100 = wall.
text 100, 0, "FrontLeft: " + str$(map(frontLeftX / 32,(frontLeftY - 24) / 32))
text 250, 0, "FrontRight: " + str$(map(frontRightX / 32,(frontRightY - 24) / 32))
text 400, 0, "BackLeft: " + str$(map(backLeftX / 32,(backLeftY - 24) / 32))
text 550, 0, "BackRight: " + str$(map(backRightX / 32,(backRightY - 24) / 32))
`Draw lines between the 4 corners which checks for collisions. This is only for testing.
`line frontLeftX, frontLeftY, frontRightX, frontRightY
`line frontLeftX, frontLeftY, backLeftX, backLeftY
`line frontRightX, frontRightY, backRightX, backRightY
`line backLeftX, backLeftY, backRightX, backRightY
`Update the screen
sync
loop
`*************************************************************************************************************************
`End Main Loop
`*************************************************************************************************************************
`Sub Routines
`*************************************************************************************************************************
`Player movement and checks for collision against walls
`*************************************************************************************************************************
player_movement:
`Get the coordinates for the 4 corners of the player. This is used for checking for collisions.
frontLeftX = playerx# + cos(wrapvalue(playerAngle#-45))*20
frontLeftY = playery# + sin(wrapvalue(playerAngle#-45))*20
frontRightX = playerx# + cos(wrapvalue(playerAngle#+45))*20
frontRightY = playery# + sin(wrapvalue(playerAngle#+45))*20
backLeftX = playerx# + cos(wrapvalue(playerAngle#-135))*20
backLeftY = playery# + sin(wrapvalue(playerAngle#-135))*20
backRightX = playerx# + cos(wrapvalue(playerAngle#+135))*20
backRightY = playery# + sin(wrapvalue(playerAngle#+135))*20
`Player movement and collision
if ready = 1
if leftkey()=1
ready = 0
t = timer() + speed
playerAngle# = wrapvalue(playerAngle# - 2)
endif
if rightkey()=1
ready = 0
t = timer() + speed
playerAngle# = wrapvalue(playerAngle# + 2)
endif
if upkey() = 1
ready = 0
t = timer()+speed
if playerAngle# >= 270 or playerAngle# >= 90 and playerAngle# < 180
if map(frontLeftX / 32,(frontLeftY - 24) / 32) < 100 and map(frontRightX / 32,(frontRightY - 24) / 32) < 100
playerx# = playerx# + cos(playerAngle#) * 2
playery# = playery# + sin(playerAngle#) * 2
endif
if map(frontLeftX / 32,(frontLeftY - 24) / 32) < 100 and map(frontRightX / 32,(frontRightY - 24) / 32) >= 100
playery# = playery# + sin(playerAngle#) * 2
endif
if map(frontLeftX / 32,(frontLeftY - 24) / 32) >= 100 and map(frontRightX / 32,(frontRightY - 24) / 32) < 100
playerx# = playerx# + cos(playerAngle#) * 2
endif
endif
if playerAngle# >= 180 and playerAngle# < 270 or playerAngle# >= 0 and playerAngle# < 90
if map(frontLeftX / 32,(frontLeftY - 24) / 32) < 100 and map(frontRightX / 32,(frontRightY - 24) / 32) < 100
playerx# = playerx# + cos(playerAngle#) * 2
playery# = playery# + sin(playerAngle#) * 2
endif
if map(frontLeftX / 32,(frontLeftY - 24) / 32) < 100 and map(frontRightX / 32,(frontRightY - 24) / 32) >= 100
playerx# = playerx# + cos(playerAngle#) * 2
endif
if map(frontLeftX / 32,(frontLeftY - 24) / 32) >= 100 and map(frontRightX / 32,(frontRightY - 24) / 32) < 100
playery# = playery# + sin(playerAngle#) * 2
endif
endif
endif
if downkey() = 1
ready = 0
t = timer()+speed
if playerAngle# >= 270 or playerAngle# >= 90 and playerAngle# < 180
if map(backLeftX / 32,(backLeftY - 24) / 32) < 100 and map(backRightX / 32,(backRightY - 24) / 32) < 100
playerx# = playerx# - cos(playerAngle#) * 2
playery# = playery# - sin(playerAngle#) * 2
endif
if map(backLeftX / 32,(backLeftY - 24) / 32) >= 100 and map(backRightX / 32,(backRightY - 24) / 32) < 100
playery# = playery# - sin(playerAngle#) * 2
endif
if map(backLeftX / 32,(backLeftY - 24) / 32) < 100 and map(backRightX / 32,(backRightY - 24) / 32) >= 100
playerx# = playerx# - cos(playerAngle#) * 2
endif
endif
if playerAngle# >= 180 and playerAngle# < 270 or playerAngle# >= 0 and playerAngle# < 90
if map(backLeftX / 32,(backLeftY - 24) / 32) < 100 and map(backRightX / 32,(backRightY - 24) / 32) < 100
playerx# = playerx# - cos(playerAngle#) * 2
playery# = playery# - sin(playerAngle#) * 2
endif
if map(backLeftX / 32,(backLeftY - 24) / 32) >= 100 and map(backRightX / 32,(backRightY - 24) / 32) < 100
playerx# = playerx# - cos(playerAngle#) * 2
endif
if map(backLeftX / 32,(backLeftY - 24) / 32) < 100 and map(backRightX / 32,(backRightY - 24) / 32) >= 100
playery# = playery# - sin(playerAngle#) * 2
endif
endif
endif
endif
return
`Draws the screen
`*******************************************************************************************************************************
draw_sprites:
`Reads values from the map array and draws the floor and walls to the screen
`tmp = 1000
for x = 0 to xsize
for y = 0 to ysize
if map(x,y) = 99
`tmp = tmp +1
paste image 99, x*32, y*32+24
`sprite tmp, x*32, y*32+24, 99
endif
if map(x,y) = 100
`tmp = tmp + 1
paste image 100, x*32, y*32+24
`sprite tmp, x*32, y*32+24, 100
endif
next y
next x
`Draws the player
sprite 1, playerx#, playery#, 1
set sprite priority 1, 1
offset sprite 1, 15, 15
rotate sprite 1, playerAngle# + 90
return