Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers DBPro Corner / Sorting the finishing positions in a 2D Horse Race

Author
Message
kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 24th Feb 2014 06:05
I used to program in basic over 20yrs ago, but not to a high standard! I started playing with DBPro 2 weeks ago (purely for my own amusement & to keep my brain active in retirement ).

I have now completed the 'engine' of a very colorful 2D horse race, the > 6 horses gallop really smoothly across the screen, whilst the scenery scrolls smoothly across the screen in the opposite direction. giving an excellent appearance of speed (Whilst in reality it usually takes over 2 min for the horses to cross the screen & reach the line)

My problem now is to decide which horses crosses the line first, second & third. The line is fixed vertically on the 'x' axis at 1100. (Screen is 1280x720).
The horses individual 'x' axis's are always increasing randomly and are held in the variables labeled red,yellow,blue,green,brown & pink (6 horses)

I need to check once in every loop to see if a horse's x axis is > 1100 & if its the first horse to >1100 then first$="horses name".
If its the second horse to cross then second$="horses name".
If its the third horse to cross then third$ = "horses name".

Every attempt (& there's been lots!!)to crack this over the last week has resulted either in The string$ changing after the horses have crossed the line or one horse occupying all 3 positions.

I have checked all 79 pages of the coded snippet section of the web page, but can't find a solution. Any suggestions gratefully received!
kebang
Derek Darkly
7
Years of Service
User Offline
Joined: 22nd Sep 2011
Location: Whats Our Vector, Victor?
Posted: 24th Feb 2014 17:23 Edited at: 24th Feb 2014 17:33
Quote: "I need to check once in every loop to see if a horse's x axis is > 1100 & if its the first horse to >1100 then first$="horses name".
If its the second horse to cross then second$="horses name".
If its the third horse to cross then third$ = "horses name"."


You could set up a variable like DIM Finish$(20) (if there are 20 horses for example) and as each horse crossed the finish line then Finish$(count)="horses name":inc count

You'd preset your count at 1, of course.
Just a rough sketch, hope it helps/makes sense.

666GO†O666
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 25th Feb 2014 08:53
In a close race, 3 horses may all cross the line in one frame. So I think it is a 2 step process:

1. Has the horse finished (if yes, add to the array that Derek Darkly suggests)

2. If there are two or more finishers in this frame, order them by their x value in the array.

There are other complications but this is a start. For example, if one horse is travelling at 10 mph and another at 60mph as they cross the line, the order may not be correctly represented by their x value. But that's step 3!

Phaelax
DBPro Master
16
Years of Service
User Offline
Joined: 16th Apr 2003
Location: Metropia
Posted: 25th Feb 2014 17:22
Track the time difference between the current frame and last frame and use that in conjunction with the horses speed and their old positions and you can figure out who crossed first or if there really was a tie

kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 26th Feb 2014 06:24
Thanks for the helpful suggestions folks. I'm still trying to solve the problem & I'll post my progress in a few days time
kebang
kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 27th Feb 2014 09:49
Now thinking of using sprites instead of images & using flagged collision detection to determine first,second & third- would this be a better approach?

kebang
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 27th Feb 2014 13:00
I don't think it will help. Your scenario is extremely simple - who passes a specific, fixed point first. Collision detection won't add any more to the mix that will help.

You will need to use CCD (Continuous Collision Detection) based on the problems you have described so far, and I'm not sure if it has the ability to report which hits first.

BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 27th Feb 2014 13:11
By the way, this may help. I have done a racing scenario like this previously, where there was no input from the user (you are simply watching a race). I precalculated the race and stored the data in a huge array, so I knew who had won before the race even started! Every race was unique and random, I simply "ran the race" before it started as a pure data exercise.

kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 28th Feb 2014 05:52
BatVink, thanks for the comments (I'm not comfortable with knowing who won before the start of the race tho!). Will not explore collisions now. The finish lane is in fact moving backwards(left) as the horses are moving forwards (right).

I couldn't see how to attach the project file here so anyone who wanted too could run the program - but here is the code

set display mode 1280,720,16
set window size 1000,600
set image colorkey 00,00,00
red=0:yellow=0:blue=0:green=0:brown=0:pink=0
bkx1=0:bkx2=0:dsp=0:in=0:cnt=0:finflag=0
st= timer()
RANDOMIZE st
load image "11.bmp",11:load image "12.bmp",12:load image "13.bmp",13:load image "14.bmp",14
load image "15.bmp",15:load image "16.bmp",16:load image "17.bmp",17:load image "18.bmp",18
load image "21.bmp",21:load image "22.bmp",22:load image "23.bmp",23:load image "24.bmp",24
load image "25.bmp",25:load image "26.bmp",26:load image "27.bmp",27:load image "28.bmp",28
load image "31.bmp",31:load image "32.bmp",32:load image "33.bmp",33:load image "34.bmp",34
load image "35.bmp",35:load image "36.bmp",36:load image "37.bmp",37:load image "38.bmp",38
load image "41.bmp",41:load image "42.bmp",42:load image "43.bmp",43:load image "44.bmp",44
load image "45.bmp",45:load image "46.bmp",46:load image "47.bmp",47:load image "48.bmp",48
load image "51.bmp",51:load image "52.bmp",52:load image "53.bmp",53:load image "54.bmp",54
load image "55.bmp",55:load image "56.bmp",56:load image "57.bmp",57:load image "58.bmp",58
load image "61.bmp",61:load image "62.bmp",62:load image "63.bmp",63:load image "64.bmp",64
load image "65.bmp",65:load image "66.bmp",66:load image "67.bmp",67:load image "68.bmp",68
load image "back01.bmp",7:load image "fence.bmp",8:load image "finish.bmp",9
load image "furlong1.bmp",1:load image "furlong2.bmp",2:load image "furlong3.bmp",3
load image "furlong4.bmp",4:load image "furlong5.bmp",5:load image "finish.bmp",6
maximize window
sync
do

for horse= 1 to 8 rem selects sequentual images for animation of horses
for dsp= 1 to 30 rem adjusts animation speed + allows time slots for adjusting horses screen poition
if red>1000 then red =1000 rem prevents horses from running off screen
if yellow>1000 then yellow =1000 rem " " "
if blue>1000 then blue =1000 rem " " "
if green>1000 then green =1000 rem " " "
if brown>1000 then brown =1000 rem " " "
if pink>1000 then pink =1000 rem " " "
paste image 7,bkx1,0: paste image 7,bkx2,0 rem scrolls background left
paste image 8,bkx1,110,1:paste image 8,bkx2,110,1 rem scrolls rear fence
if cnt=12 then paste image 6,bkx2-39,16,1 rem displays finish line
if cnt=2 then paste image 5,bkx2-39,40,1 rem displays 5 furlong post
if cnt=4 then paste image 4,bkx2-39,40,1 rem displays 4 furlong post
if cnt=6 then paste image 3,bkx2-39,40,1 rem displays 3 furlong post
if cnt=8 then paste image 2,bkx2-39,40,1 rem displays 2 furlong post
if cnt=10 then paste image 1,bkx2-39,40,1 rem displays 1 furlong post
paste image 10+horse,red,90,1 rem draws individual animation horse frames
paste image 20+horse,yellow,170,1 rem " " "
paste image 30+horse,blue,250,1 rem " " "
paste image 40+horse,green,330,1 rem " " "
paste image 50+horse,brown,410,1 rem " " "
paste image 60+horse,pink,490,1 rem " " "
paste image 8,bkx1,570,1:paste image 8,bkx2,570,1 rem draws front fence

wait 1
dec bkx1: bkx2=bkx1+1280 rem decreases x axis
if bkx1=-1280 then bkx1=0:inc cnt rem resets x axis + counts screens
q=rnd(17)+1
if dsp>28 then gosub min rem adust poition of one horse
if dsp<4 then gosub posadj rem adjusts horse position of 2 horses
next dsp

if count =1 then col=18 + rnd(20)+1 rem selects which 2 horse(s) will be moved in posadj:
inc count:if count=25 then count=0 rem prevents col being changed too rapidly
gosub posadj rem adjusts horse position of 2 horses

next horse
n=rnd(5)+1 rem selects indivual horse for min:
loop
posadj:
q=rnd(1)
if cnt>11 then q=1

if col =19 then inc red
if col =20 then inc yellow
if col =21 then inc blue
if col =22 then inc green
if col =23 then inc brown
if col =24 then inc pink


if col= 25 and q=1 then inc red: inc yellow
if col= 26 and q=1 then inc red: inc blue
if col= 27 and q=1 then inc red:inc green
if col= 28 and q=1 then inc red:inc brown
if col= 29 and q=1 then inc red:inc pink

if col= 30 and q=1 then inc yellow:inc blue
if col= 31 and q=1 then inc yellow: inc green
if col= 32 and q=1 then inc yellow:inc brown
if col= 33 and q=1 then inc yellow:inc pink

if col= 34 and q=1 then inc blue:inc green
if col= 35 and q=1 then inc blue:inc brown
if col= 36 and q=1 then inc blue:inc pink

if col= 37 and q=1 then inc green:inc brown
if col= 38 and q=1 then inc green:inc pink

if col= 39 and q=1 then inc brown:inc pink
return

min:
if n=1 then inc red
if n=2 then inc yellow
if n=3 then inc blue
if n=4 then inc green
if n=5 then inc brown
if n=6 then inc pink

return
BatVink, thanks for the comments (I'm not comfortable with knowing who won before the start of the race tho!)
kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 28th Feb 2014 05:54
The finish line moving backwards was a change I made after the first post, sorry for the confusion!
kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 28th Feb 2014 07:53
The finish line moving backwards was a change I made after the first post, sorry for the confusion!
kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 1st Mar 2014 04:14
Apologies for the double posts, as a newcomer to the forum my posts are not displayed or acknowledged straight away so I didn't realize I had already posted it.....

This gosub seems to work 99% of the time, but it will malfunction in a dead heat. When this happens one of horses 'dead heating' is ignored completely, and the following horses are moved up the finishing order.

poscheck:
if red+170=fini then inc flag: rd=flag
if yellow+170=fini then inc flag: yw=flag
if blue+170=fini then inc flag:be=flag
if green+170=fini then inc flag:gn=flag
if brown+170=fini then inc flag:bn=flag
if pink+170=fini then inc flag:pk=flag

if rd=1 then first$="red "
if rd=2 then second$="red "
if rd=3 then third$="red "

if yw=1 then first$="yellow "
if yw=2 then second$="yellow "
if yw=3 then third$="yellow "

if be=1 then first$="blue "
if be=2 then second$="blue "
if be=3 then third$="blue "

if gn=1 then first$="green "
if gn=2 then second$="green "
if gn=3 then third$="green "

if bn=1 then first$="brown "
if bn=2 then second$="brown "
if bn=3 then third$="brown "

if pk=1 then first$="pink "
if pk=2 then second$="pink "
if pk=3 then third$="pink "

return

rem the finish line x axis count down is now calculated by a countdown of variable 'fini' which is set at 16641 at the start of the race. the addition of 170 to the horse image x axis compensates for the length of the image
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 1st Mar 2014 08:45
The most important question is, do you want a scenario where you have a dead heat? It might be that a dead heat causes other complications in your game and you need to rule out this possibility for the same of God gameplay. In which case, we are chasing the wrong problem.

One of the reasons (there are many) that I precalculate my race is to prevent a dead heat.

kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 1st Mar 2014 10:00
You are right BatVink, I do not want a dead heat, but I'm a complete duffer with arrays......... I suppose that by doing as you suggest it would also be possible to play back the finish in slow motion, which would be a bonus.
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 1st Mar 2014 16:26
There is another solution which involves changing your position values (red, pink etc) to floats. The easiest way to fix this is to add the following at the top of the program:

global red as float
global blue as float
etc...

Now you can make your horse movement more granular. where you have increased red like so:

inc red

change it to something like

red = red + (800 + ((rnd(200) + 1) * 0.001))

This increases red by between 0.800 and 1.000 (e.g 0.937)

You are now 1000 times less likely to get a dead heat. You can use the rounded version of the position to place your images on the screen.

You still need to deal with the eventuality that you may get a heat. I would do this by picking one of the two horses at random and moving it forward an extra 0.001 units before determining first and second.

kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 2nd Mar 2014 05:12
I'm certainly going to play with this! However before I type a line one thing crosses my mind. It's 200 to 1 that red float will not be a whole number. therefore the same odds apply to red float = 'fini', its 200 to 1 than rd gets flagged.

If, for checking, all the coloured floats are rounded then surely the same chances for a tie exist with this model as with my original model?
BatVink
Moderator
16
Years of Service
User Offline
Joined: 4th Apr 2003
Location: Gods own County, UK
Posted: 2nd Mar 2014 12:21 Edited at: 2nd Mar 2014 12:22
You would have 2 things going on. On screen you can only ever move a minimum of one pixel. But the value behind position 1374 for example may be 1373.72. It's this value that you use to check the winner. You'll be checking for "greater than" the finishing post rather than "equal to"the post. Where 2 cross the line in the same frame, there will invariably be a difference in the decimals. But you'll still have to cater for the rarer but still possible chance of a tie.

If you've been getting a tie every tenth race, you're now only going to get a tie 1000 races. Maybe that's worth keeping as an interesting feature?

kebang
5
Years of Service
User Offline
Joined: 24th Feb 2014
Location:
Posted: 9th Mar 2014 16:11
Thanks for the help. This isn't as simple as I thought it would be..... I've made sevral attempts, but the flags are causing me probs. (horse triggers 'flags' multiple times filling all winning/position. Will continue to work on this & ask for further help if I'm totally stumped. (This is meant to be a thinking process to keep my mental processes working in old age )

Login to post a reply

Server time is: 2019-04-26 12:05:47
Your offset time is: 2019-04-26 12:05:47