Drawing lines - BASIC vs machine code

bbc micro/electron/atom/risc os coding queries and routines
Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Drawing lines - BASIC vs machine code

Post by Adam James » Mon Jul 20, 2020 10:58 pm

Some questions about drawing lines on the BBC micro:

1) If I were to execute in BASIC something like this, to draw a vertical line in the bottom left corner:

MOVE 0,0: DRAW 0,100

Am I right in assuming that there is little speed benefit in trying to do that in assembler instead? Because mostly what is happening, is a pre-built line drawing routine, in machine code, is being executed, and it will be as fast as possible?

2) If I were to write a loop in BASIC such that the line appeared to move to the right (each cycle drawing the line at the new position, after e.g. drawing the line in the previous position using the background colour), would it be much faster in assembler? And would the speed increase be mainly due to the looping logic not needing to be interpreted?

3) Purely in BASIC, are there any fancy tricks to optimise (2), other than using integer, built-in variables?

User avatar
FourthStone
Posts: 1028
Joined: Thu Nov 17, 2016 2:29 am
Location: Brisbane, Australia
Contact:

Re: Drawing lines - BASIC vs machine code

Post by FourthStone » Mon Jul 20, 2020 11:52 pm

My 2c...

1) Basic uses generic drawing routines, so every time you make a call to the line drawing routine it has to go through initialisation, work out X,Y coordinates relative to the character based screen memory, then plot the all pixels.

For a straight line you could save a lot of time by using assembler as your routine would be optimised for that single purpose and using look up tables you could avoid a lot of the coordinate translation.

2) Yes assembler will be much faster at this and little tricks like only redrawing changes instead of the entire line will speed up the routine even more.

3) You could probably do some memory pokes if the line you're drawing isn't very large, poking a few bytes to memory could possibly be faster than the basic line drawing routines for certain types of line e.g. horizontal

User avatar
richardtoohey
Posts: 3986
Joined: Thu Dec 29, 2011 5:13 am
Location: Tauranga, New Zealand
Contact:

Re: Drawing lines - BASIC vs machine code

Post by richardtoohey » Tue Jul 21, 2020 4:59 am

I wonder if the VDU commands would be 0.005% faster than the BASIC versions?

e.g. something like VDU 25,0,100,100,25,1,0,100

The VDU equivalent of the MOVE and DRAW commands.

They don't help here, just wondering! :oops:

User avatar
ChrisB
Posts: 78
Joined: Wed Oct 05, 2011 10:37 pm
Location: Surrey
Contact:

Re: Drawing lines - BASIC vs machine code

Post by ChrisB » Tue Jul 21, 2020 8:32 am

Richard - I've spent far too much time playing around with this today. In short - no. The fastest way to make BASIC move/draw some lines is with MOVE & DRAW combinations.

Doing PLOT commands or VDU commands (even when grouped into two byte blocks with ; ) is slower. I assume you're mostly seeing the overhead of the BASIC interpreter. If you make a string of the VDU commands and then PRINT that it is slightly faster - but changing those commands is then very slow/hard. Even calling an assembler routine that feeds the byte string to OSWRCH is only marginally faster than move/draw - and even then exactly how this is called (Integer variable for location etc.) makes a difference.

As FourthStone says an assembler routine - especially a specialised one - is probably going to be an order of magnitude faster.

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Tue Jul 21, 2020 9:01 am

Thanks people, lots of interesting thoughts and tests there!
FourthStone wrote:
Mon Jul 20, 2020 11:52 pm
My 2c...

1) Basic uses generic drawing routines, so every time you make a call to the line drawing routine it has to go through initialisation, work out X,Y coordinates relative to the character based screen memory, then plot the all pixels.

For a straight line you could save a lot of time by using assembler as your routine would be optimised for that single purpose and using look up tables you could avoid a lot of the coordinate translation.

2) Yes assembler will be much faster at this and little tricks like only redrawing changes instead of the entire line will speed up the routine even more.

3) You could probably do some memory pokes if the line you're drawing isn't very large, poking a few bytes to memory could possibly be faster than the basic line drawing routines for certain types of line e.g. horizontal
Great explanations, thank you. I hadn't considered that even the built-in machine code routines would not be optimal, due to having to translate coordinates, and not being optimised for pure vertical or horizontal lines.

I'm wondering if I might try, for my first ever bit of assembler on the BBC, a routine just to draw vertical lines in Mode 2, and whether that would be so much faster than BASIC commands that I could get away with doing everything else in BASIC.

User avatar
jms2
Posts: 2677
Joined: Mon Jan 08, 2007 6:38 am
Location: Derby, UK
Contact:

Re: Drawing lines - BASIC vs machine code

Post by jms2 » Tue Jul 21, 2020 12:36 pm

Sounds like a good plan. What you should do next is define exactly what you want, ie:

- Do you need to be able to draw lines at all 160 x-positions?
- What heights of lines do you need, and again do you need to cater for the full range of 256 pixels?
- What colours are required?
- What happens to the background, ie does the line overwrite the background, or EOR it?

These decisions are important because the general design principle for this kind of routine is normally to do one specific thing as quickly as possible. The more generalisations you put in, the slower and more complicated it will get.

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Tue Jul 21, 2020 1:36 pm

jms2 wrote:
Tue Jul 21, 2020 12:36 pm
Sounds like a good plan. What you should do next is define exactly what you want, ie:

- Do you need to be able to draw lines at all 160 x-positions?
- What heights of lines do you need, and again do you need to cater for the full range of 256 pixels?
- What colours are required?
- What happens to the background, ie does the line overwrite the background, or EOR it?

These decisions are important because the general design principle for this kind of routine is normally to do one specific thing as quickly as possible. The more generalisations you put in, the slower and more complicated it will get.
My quick mock-up in BASIC uses a very much reduced area in the centre of the screen, for speed reasons, so that could limit the X and Y ranges. But then I may be so amazed by the speed of machine code that I change that. I'd want colours 1-7 and I think always using EOR would work well.

It's occurred to me though, as I was mocking it up in BASIC and seeing what slowed things down, as well as line count (obviously!), when I then introduced floating-point multiplication to move their X and Y positions, that was a significant slow-down as well.

So I suppose I have a similar question for handling numbers as I do for drawing lines:

If people are writing machine code and handling floats, do they write their own routines for e.g. multiplication from scratch, or do they call built-in routines that are already as fast as can be?

User avatar
BigEd
Posts: 3420
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: Drawing lines - BASIC vs machine code

Post by BigEd » Tue Jul 21, 2020 2:31 pm

I'd say floats are very rarely the answer, when you want performance. Integer arithmetic is much faster, and if you scale the integers by, say, 256, then you can still get accuracy and fractional answers. In assembly language, you'd use 1-byte or 2-byte values whenever you can get away with it, because 4 byte arithmetic (Basic's integers) are always going to be slower.

User avatar
jms2
Posts: 2677
Joined: Mon Jan 08, 2007 6:38 am
Location: Derby, UK
Contact:

Re: Drawing lines - BASIC vs machine code

Post by jms2 » Tue Jul 21, 2020 3:02 pm

Also... if this is a game, do you need the lines to be moving up (or down) the screen, like laser bolts? If they are going to have to move, and they are long lines, you'd ideally do it by lengthening one end and shortening the other, rather than redraw the whole line. Your drawing/undrawing method might be influenced by the system you use to keep track of the positions of all the moving objects as well.

The good news is that both the X co-ordinate and the Y co-ordinate fit into one byte each in Mode 2. As BidEd suggests, if you use two bytes for each one, where the least significant byte represents fractions of a pixel, you can easily have sub-pixel movement.

AJW
Posts: 906
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by AJW » Tue Jul 21, 2020 7:30 pm

Somebody postee a link on the Acornsoft Elite thread about drawing fast lines -Bresenham or something.

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Tue Jul 21, 2020 8:47 pm

I suppose I'd better give the full details as it seems there are all sorts of angles I haven't thought of.

Basically I started by wondering about "bringing Deathchase for the ZX Spectrum to the BBC": https://www.youtube.com/watch?v=djHoBBrtzKY

I like the very simple concept. Just dodging the trees would be fun enough as they increased in number.

Then I thought I probably would never put in the effort to learn assembler, so how much of the concept could I develop in BASIC?

My first thought was that the trees just need to be lines. My second thought is that they probably don't need to get thicker the closer they get in order to produce a decent 3D effect, what with the tricks that can be played on the brain.

All my thoughts then turned to making an extremely elegant, simple game that could take advantage of very simple concepts - it's all about minimalism, seeing what can be done with BASIC, and it all boils down to lines and colours.

So:
  • A tiny viewport in the centre of the screen that can be thought of as e.g. a periscope in a tank.
  • All that you see is vertical lines or "poles" to dodge, collect or destroy
  • You are constantly moving forward, and can just turn left, right or fire
  • The pole colours will have meaning and dictate whether they should be dodged, collected or destroyed
  • For collision detection (have you collided with a pole?) there is a horizontal bar at the bottom of the periscope view. It's an easy way to control difficulty - make it wider and it's harder to avoid things. It can also change in colour, indicating what poles to dodge/collect/destroy. There could even be two horizontal bars one above the other, of different widths and different colours, the narrower one for collecting poles.
  • The 3D effect can be a very simple fudge, since poles disappear for good once they go out of view.
This is my first attempt to see what BASIC could do. It was written to handle up to 11 poles at once, but 5 seems optimal in terms of speed vs how difficult it might be to avoid them. Any more and it slows down to the point where it actually seems like it might be easier!

There is no code for steering and collision detection. I think that would be simple (certainly the collision detection) but also suspect it would become too slow to be enjoyable given how much it slowed down with the other simple (but floating point) maths:

Code: Select all

   10MODE2
   12MOVE240,508:DRAW1040,508:DRAW1040,292:DRAW240,292:DRAW240,508
   14MOVE620,296:DRAW660,296
   15DIMX%(10):DIMY%(10):DIMC%(10)
   17FORI%=0TO10:X%(I%)=RND(640)+340:Y%(I%)=RND(32)+4:C%(I%)=RND(7):NEXT
   18REPEAT
   20FORI%=0TO4
   25GCOL0,0
   30MOVEX%(I%),500-Y%(I%):DRAWX%(I%),500
   35X%(I%)=X%(I%)+(X%(I%)-640)*.1:Y%(I%)=Y%(I%)*1.3
   36IFY%(I%)>200ORABS(640-X%(I%))>392THENY%(I%)=RND(32)+4:X%(I%)=RND(640)+340:C%(I%)=RND(7)
   37GCOL0,C%(I%)
   40MOVEX%(I%),500-Y%(I%):DRAWX%(I%),500
   50NEXT
   60UNTIL0
I figured I'd need to use floating point numbers to get the 3D effect, but now I'm not so sure.

If anyone can spot a way to optimise this kind of stuff in BASIC, or what the biggest gains would be in terms of using assembler, I'd be grateful for any pointers!

User avatar
jms2
Posts: 2677
Joined: Mon Jan 08, 2007 6:38 am
Location: Derby, UK
Contact:

Re: Drawing lines - BASIC vs machine code

Post by jms2 » Tue Jul 21, 2020 9:50 pm

That's very good actually! It's an impressive 3D effect for so little code.

One optimisation I can spot straight away is that if you set the origin of the screen to the centre, then you wouldn't need to do "-640" to the x co-ordinate every time. The command to do this is:

VDU 29,640;0;

User avatar
jms2
Posts: 2677
Joined: Mon Jan 08, 2007 6:38 am
Location: Derby, UK
Contact:

Re: Drawing lines - BASIC vs machine code

Post by jms2 » Tue Jul 21, 2020 9:58 pm

And, you can avoid doing any floating point maths quite easily by using DIV. It's better to divide by 8 than by 10 (I think), and it doesn't seem to affect the appearance.

Code: Select all

   10MODE2
   20MOVE240,508:DRAW1040,508:DRAW1040,292:DRAW240,292:DRAW240,508
   30MOVE620,296:DRAW660,296
   35VDU29,640;0;
   40DIMX%(10):DIMY%(10):DIMC%(10)
   50FORI%=0TO10:X%(I%)=RND(640)-320:Y%(I%)=RND(32)+4:C%(I%)=RND(7):NEXT
   60REPEAT
   70FORI%=0TO4
   80GCOL0,0
   90MOVEX%(I%),500-Y%(I%):DRAWX%(I%),500
  100X%(I%)=X%(I%)+(X%(I%) DIV8):Y%(I%)=Y%(I%)+(3*Y%(I%) DIV8)
  110IFY%(I%)>200ORABS(X%(I%))>320THENY%(I%)=RND(32)+4:X%(I%)=RND(640)-320:C%(I%)=RND(7)   
  120GCOL0,C%(I%)
  130MOVEX%(I%),500-Y%(I%):DRAWX%(I%),500
  140NEXT
  150UNTIL0
  
This can display 7 (maybe 8 ) poles at roughly the same speed as the original.
Last edited by 1024MAK on Thu Jul 23, 2020 6:52 pm, edited 1 time in total.
Reason: Edited to add a space between the 8 and the ) to prevent the unwanted cool smiley...

User avatar
jms2
Posts: 2677
Joined: Mon Jan 08, 2007 6:38 am
Location: Derby, UK
Contact:

Re: Drawing lines - BASIC vs machine code

Post by jms2 » Tue Jul 21, 2020 10:39 pm

This is my attempt at providing a "steering" function, using Z and X. No speed problem, but my maths isn't good enough to create a convincing steering effect! I'm sure you can do better...

Code: Select all

   10MODE2
   20MOVE240,508:DRAW1040,508:DRAW1040,292:DRAW240,292:DRAW240,508
   30MOVE620,296:DRAW660,296
   35VDU29,640;0;
   40DIMX%(10):DIMY%(10):DIMC%(10)
   50FORI%=0TO10:X%(I%)=RND(640)-320:Y%(I%)=RND(32)+4:C%(I%)=RND(7):NEXT
   51 
   52DX%=0
   53 
   60REPEAT
   70FORI%=0TO8
   80GCOL0,0
   90MOVEX%(I%),500-Y%(I%):DRAWX%(I%),500
   95XA%=X%(I%) DIV 8:XB%=ABS(XA% DIV 2)*DX%
  100X%(I%)=X%(I%)+XA%+XB%:Y%(I%)=Y%(I%)+(3*Y%(I%) DIV8)
  110IFY%(I%)>200ORABS(X%(I%))>320THENY%(I%)=RND(32)+4:X%(I%)=RND(640)-320:C%(I%)=RND(7)   
  120GCOL0,C%(I%)
  130MOVEX%(I%),500-Y%(I%):DRAWX%(I%),500
  140NEXT
  141DX%=DX%+INKEY(-98)-INKEY(-67)
  142IF DX%<-4 DX%=-4
  143IF DX%>4 DX%=4
  150UNTIL0

User avatar
jgharston
Posts: 4118
Joined: Thu Sep 24, 2009 12:22 pm
Location: Whitby/Sheffield
Contact:

Re: Drawing lines - BASIC vs machine code

Post by jgharston » Tue Jul 21, 2020 11:12 pm

FourthStone wrote:
Mon Jul 20, 2020 11:52 pm
1) Basic uses generic drawing routines, so every time you make a call to the line drawing routine it has to go through initialisation, work out X,Y coordinates relative to the character based screen memory, then plot the all pixels.
No it doesn't, the operating system does that. The whole point of Basic *not* doing it is so that *anything* can use the graphics routines. All Basic does is purely, simples and exactly, collect the parameters and pass them to the MOS. Basic has no idea, cares not a jot, and must not care a jot what the VDU driver does with them, that is entirely and completely the responsibility of the VDU driver.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.32
(C) Copyright J.G.Harston 1989,2005-2020
>_

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Tue Jul 21, 2020 11:22 pm

jms2 wrote:
Tue Jul 21, 2020 9:50 pm
That's very good actually! It's an impressive 3D effect for so little code.
I have to admit I was pretty encouraged to pursue the idea once I saw it running, but was worried about how slow it would become in pure BASIC once all the logic was in place.
jms2 wrote:
Tue Jul 21, 2020 9:50 pm
One optimisation I can spot straight away is that if you set the origin of the screen to the centre, then you wouldn't need to do "-640" to the x co-ordinate every time. The command to do this is:

VDU 29,640;0;

...

And, you can avoid doing any floating point maths quite easily by using DIV. It's better to divide by 8 than by 10 (I think), and it doesn't seem to affect the appearance.

...

This is my attempt at providing a "steering" function, using Z and X. No speed problem...
Excellent stuff, thank you. I wasn't aware of the ability to change the origin and I have to admit I didn't even know there was a statement for integer division!

I figure if, once all the logic is in place for an actual game, it can still run as fast as it did originally with 5 poles, then it's worth going for it. Just instinctively it feels like that would be a decent challenge. You've given me a lot of hope that this is doable in BASIC and I know what I'll be doing tomorrow!

Naomasa298
Posts: 391
Joined: Sat Feb 16, 2013 12:49 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Naomasa298 » Wed Jul 22, 2020 11:58 am

I note a distinct lack of Ewoks in this game.

User avatar
BeebMaster
Posts: 3621
Joined: Sun Aug 02, 2009 5:59 pm
Location: Lost in the BeebVault!
Contact:

Re: Drawing lines - BASIC vs machine code

Post by BeebMaster » Wed Jul 22, 2020 2:36 pm

Going back to the original question about what is faster, I haven't found any difference at all in BASIC using MOVE/DRAW, or PLOT, or VDU25. I had to draw several lines to get any sort of reading, just drawing one line was taking less than a centisecond, but all methods here are identical in timing:
capture37.png
capture39.png
capture40.png
Image

User avatar
BeebMaster
Posts: 3621
Joined: Sun Aug 02, 2009 5:59 pm
Location: Lost in the BeebVault!
Contact:

Re: Drawing lines - BASIC vs machine code

Post by BeebMaster » Wed Jul 22, 2020 2:58 pm

Concatenating the VDU commands into one doesn't help:
capture41.png
Or even doing it all from assembler (apart from the 3cs assembly time). This surprised me, I thought machine code would be quicker:
capture43.png
Image

AJW
Posts: 906
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by AJW » Wed Jul 22, 2020 3:05 pm

Sane thing here when I tried blotting out a rectangle with "plot 85" in assembler. It seemed no gain on BASIC.

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Wed Jul 22, 2020 4:43 pm

Thanks for the continued investigation people!

I'm shocked to declare this thing is possibly now an actual game. I just played it, trying to get the highest score I could, and it actually played well and felt worthwhile. I certainly feel I've achieved my original aim of writing a minimalist "3D" game in BASIC that has the same kind of "why is something this simple so enjoyable?" feel of Deatchcase on the Spectrum.

I came up with some of my own optimisations. If you note the visual effect in the first version, basically the lines always touch the top of the periscope view. This made possible the speed optimisation of not having to calculate the top of each line, but the perspective it gave was as if the horizon was just out of view above the periscope.

So just for fun I tried creating a more typical perspective: sitting in a vehicle, some height off the ground, but facing straight forwards. That required maths for the top and bottom of each line, and it got unpleasantly slow. But it looked GREAT so I was determined to find a way to keep it.

In the end I pre-calculated a set number of Y-bottom and Y-top values for lines and just looked up those values from an array at each cycle. Each line is always at a certain vertical "step" between 0-20, 20 being right in front of the vehicle and the point of collision detection.

I'm pleased to say it worked a treat and I could happily have 7 poles on the screen and it looked quite good.

However, I've now finished all the "game logic", it has slowed, and I feel I can only have 3 or 4 poles at once for decent speed.

I've actually set it to 3 poles by default for now. Once you have made some progress and your 'absorber' is quite wide, 3 poles becomes a decent challenge. But then so does 4. It's a fine balance between speed and obstacles to avoid.

I'd be interested in people's views on this:

1) Is this a game? (I think it is, but then it's my baby so I would!)
2) 3 or 4 poles - don't decide till you get as far as you can, it may change your mind!
3) Suggestions for optimisations. I've just realised that in my messing around I've lost jms2's origin-shift code, so that can go back in. But can anyone spot anything else that would have big gains? I'm executing 2 SOUND statements at every cycle which seems overkill for example, but I can't think how else to get a pitch change when you slow down.
4) WHY DOES IT ALWAYS GO 'BEEP' at the very start just before the energy bar starts going up? I think I'm going blind but I can't see what is causing that! I want it to make the sound as the energy bar is animated going up, but not the beep at the start!

Thanks in advance!

Note I'm writing this and testing it on a real BBC. When I just pasted this code into my BeebEm it seemed a bit faster and smoother for some reason!

Code: Select all

    2MODE7:VDU23,1,0;0;0;0:PROCINST
    5MODE2:VDU23,1,0;0;0;0
   10DIMYB%(20):DIMYT%(20):DIMD%(20)
   20FORI=1TO20:YB%(I)=340-I^1.23:YT%(I)=340+I^1.693:D%(20-I)=8+I*2:NEXT
   22REMFORI=1TO10:YB%(I)=340-I^1.6:YT%(I)=340+I^2.2:NEXT
   30DIMR%(3):R%(0)=1:R%(1)=2:R%(2)=4:R%(3)=7
   32DIMX%(10):DIMC%(10):DIMS%(10)
   40R%=0:E%=100:A%=-1:L%=620:M%=660:SC%=0
   42GCOL0,7
   45PRINT
   47FORI%=0TO10:X%(I%)=RND(440)+440:C%(I%)=RND(7):S%(I%)=RND(2)
   50PRINTTAB(1,7);"ENERGY"
   60PRINTTAB(2,9);"SCORE 0"
  120MOVE340,508:DRAW940,508:DRAW940,292:DRAW340,292:DRAW340,508
  130GCOL0,R%(0):MOVEL%,296:DRAWM%,296
  135FORI%=1TO10:PRINTTAB(7+I%,7);"*":SOUND1,-10,50+I%*2,1:FORJ%=1TO300STEP1:NEXTJ%:NEXTI%
  160REPEAT:FORI%=0TO2
  170SOUND&11,-2,2+INKEY(-1)*2,255:SOUND&12,-2,3+INKEY(-1)*2,255
  190GCOL0,0:MOVEX%(I%),YB%(S%(I%)):DRAWX%(I%),YT%(S%(I%))
  212D%=0:IFINKEY(-98)THEND%=D%(S%(I%))ELSEIFINKEY(-67)THEND%=-D%(S%(I%))
  215X%(I%)=X%(I%)+(X%(I%)-640)DIV(8*(1-INKEY(-1)))+D%:S%(I%)=S%(I%)+2+INKEY(-1)
  217IFS%(I%)>20ANDX%(I%)>=L%ANDX%(I%)<=M%THENA%=FNC(I%)
  220IFS%(I%)>20ORABS(640-X%(I%))>292THENS%(I%)=RND(2):X%(I%)=RND(440)+440:C%(I%)=RND(7)
  240GCOL3,C%(I%):MOVEX%(I%),YB%(S%(I%)):DRAWX%(I%),YT%(S%(I%))
  250IFR%=3ANDINKEY(-74)THENZ%=FNL
  260NEXT:UNTILA%=0
  261SOUND&11,0,0,0:SOUND&12,0,0,0:SOUND&13,0,0,0:ENVELOPE3,128,0,0,0,0,0,0,0,0,0,-1,126,0:SOUND4,3,6,1
  262PRINTTAB(5,30);"Press SPACE"
  265G$=GET$:IFG$<>" "THENGOTO265
  270CLS:GOTO40
  300DEFFNC(I%)
  305IFR%(R%)<>C%(I%)ORR%=3THENSOUND3,-15,0,2:E%=E%-10:R%=0:GCOL0,R%(R%):MOVEL%,296:DRAWM%,296:PRINTTAB(8+E%/10,7);" ":=E%
  310SOUND3,-7,100,1:R%=R%+1:IFR%=4THENR%=0
  311SC%=SC%+50:PRINTTAB(8,9);SC%
  312IFR%=3THENL%=L%-8:M%=M%+8
  313GCOL0,R%(R%):MOVEL%,296:DRAWM%,296
  315=-1
  400DEFFNL
  403ENVELOPE1,1,4,-4,8,1,1,1,0,0,0,-60,60,60:SOUND1,1,120,10:SOUND2,1,124,10:SOUND3,1,128,10
  404GCOL3,7:MOVEL%,308:MOVEM%,308:PLOT85,M%,340:MOVEL%,340:PLOT85,L%,308
  405R%=0:GCOL0,R%(R%):MOVEL%,296:DRAWM%,296
  410FORJ%=0TO3
  420IFC%(J%)=7ANDX%(J%)>=L%ANDX%(J%)<=M%THENGCOL3,C%(J%):MOVEX%(J%),YB%(S%(J%)):DRAWX%(J%),YT%(S%(J%)):S%(J%)=RND(2):X%(J%)=RND(440)+440:C%(J%)=RND(7):SC%=SC%+200:PRINTTAB(8,9);SC%:ENVELOPE3,128,0,0,0,0,0,0,0,0,0,-2,100,0:SOUND4,3,5,1
  425NEXT
  427GCOL3,7:MOVEL%,308:MOVEM%,308:PLOT85,M%,340:MOVEL%,340:PLOT85,L%,308
  430=-1
  500REPEAT: FOR I=-1TO-127STEP-1:IFINKEY(I)THENPRINTI
  510NEXT:UNTIL0
 1000DEFPROCINST
 1005PRINT
 1010PRINT"POLE RUNNER"
 1020PRINT
 1030PRINT"You find yourself hurtling along the"
 1035PRINT"barren surface of Planet RGB in your"
 1040PRINT"Pole Runner Mk3 hover vehicle."
 1045PRINT
 1050PRINT"Your mission: to eliminate as many of"
 1055PRINT"the evil WHITE POLES as you can. But"
 1060PRINT"before you can fire your LASER beam"
 1065PRINT"you must first charge it, by absorbing"
 1070PRINT"a RED, GREEN and BLUE pole, in that"
 1075PRINT"order. Absorb poles by bumping into"
 1076PRINT"them with your front-mounted ABSORBER."
 1080PRINT
 1082PRINT"If you hit a pole of a colour that your"
 1084PRINT"ABSORBER is not expecting, you will"
 1086PRINT"take damage. When your LASER is charged"
 1087PRINT"your ABSORBER will widen. This is good,":PRINT"and bad..."
 1088PRINT
 1090PRINT"Z-Left X-Right SHIFT-Slow RETURN-Fire"
 1100PRINT
 1110PRINT"PRESS A KEY TO GET STARTED!";
 1900G$=GET$
 2000ENDPROC

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Wed Jul 22, 2020 5:10 pm

I've just played this on the emulator, trying to get as far as I can, since I'm now on the PC.

I like how it plays with 3 poles. I got a score of over 9700 and by that point the 'absorber' is extremely wide and I had to keep the brakes slammed on constantly and keep turning constantly in one direction - the turning is steep enough to ensure all poles will miss you if e.g. you are turning left and a pole comes into view on the extreme left - by the time it gets to you it will miss you, to the right. So you can keep that up until you see a pole of the desired colour and then attempt to "pick it off".

I suspect it may be possible to break the game and have the absorber reach the full width of the periscope.

I think I'll either stop the absorber increasing in width over a certain point, or at that point, reset it and award huge bonus points.

Of course I could always reset the absorber width, award bonus points, AND increase the pole count to 4! I'd be more tempted to do that if somebody can help me optimise the speed.

If anybody has any similar low-cost gameplay ideas I'd be interested to hear them!

Edit: One feature I'll definitely be adding is an alert sound (and possibly a visual) for when the LASER is charged up and you are ready to fire at a white pole. I really am not sure what more the game needs, considering the goal is to keep it as minimal as possible while still being fun. It may be all about speed optimisations now?

User avatar
jms2
Posts: 2677
Joined: Mon Jan 08, 2007 6:38 am
Location: Derby, UK
Contact:

Re: Drawing lines - BASIC vs machine code

Post by jms2 » Wed Jul 22, 2020 6:06 pm

That's really good, it does feel like a game!

The reason for your extra beep is that your two VDU23 statements need to end with an extra colon. At the moment you are one byte short, so the next thing you print (a carriage return) gets swallowed by the VDU23 statement and then after that you send a 7 as part of the PRINT TAB statement, which is a beep.

AJW
Posts: 906
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by AJW » Wed Jul 22, 2020 6:40 pm

Lookups for the subtracts andDiv8s might gain you say 10%.

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Wed Jul 22, 2020 7:24 pm

Naomasa298 wrote:
Wed Jul 22, 2020 11:58 am
I note a distinct lack of Ewoks in this game.
Your observation is verifiable:) I sense I may have caused some disappointment! And that I am missing something here... on top of the absent Ewoks.
jms2 wrote:
Wed Jul 22, 2020 6:06 pm
That's really good, it does feel like a game!

The reason for your extra beep is that your two VDU23 statements need to end with an extra colon. At the moment you are one byte short, so the next thing you print (a carriage return) gets swallowed by the VDU23 statement and then after that you send a 7 as part of the PRINT TAB statement, which is a beep.
Thanks, good to know I'm not entirely deluded! I've just played it again now, it's really not bad IMHO. Definitely going to be doing some gameplay tweeks but fundamentally I think it's sound.

Thanks for the info about the VDU statements. That makes so much sense, as another thing I couldn't work out was why characters were not appearing at the start of the pages - I was having to enter "PRINT" statements before the desired text as a workaround:)
AJW wrote:
Wed Jul 22, 2020 6:40 pm
Lookups for the subtracts andDiv8s might gain you say 10%.
Thanks. I'll be reinstating jsm2's get-rid-of-subtracts-by-adjusting-the-origin optimisation. It disappeared by accident, as did a lot of my own code due to saving over the wrong versions of files!

Re the idea of lookups for DIV8s, do you mean for the X coordinate calculations? I did wonder if I could use lookups for those like I did for the Y coordinates, but wasn't sure, as there could be a huge number of values. Not only does a pole start at a random X position, but at any point it can be shifted left or right by steering. Not sure how to keep track of that with lookups. Or am I missing your meaning?

AJW
Posts: 906
Joined: Sun Feb 15, 2004 2:01 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by AJW » Wed Jul 22, 2020 7:38 pm

What range of values do you need to DIV8 by? store all results and index by that value.

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Wed Jul 22, 2020 11:04 pm

AJW wrote:
Wed Jul 22, 2020 7:38 pm
What range of values do you need to DIV8 by? store all results and index by that value.
It's knowing what index to use that I'm struggling to get my head around.

For the Y axis lookups, it was straightforward: every cycle, the index increases by 1 (if braking) or 2.

For the X axis lookups, given the x position changes dependent on the current x position (e.g. the more to the left it currently is, the more to the left it will be on the next cycle), and the direction of steering, and whether breaking or not, I can't see how to say "on the previous cycle the X index for this line was this, so on this cycle it will now be this". It almost feels like, to work out the index, I'd need to use the same maths I'm already using.

I'm not sure if I'm explaining my lack of comprehension well because I feel I'm missing something!

User avatar
jms2
Posts: 2677
Joined: Mon Jan 08, 2007 6:38 am
Location: Derby, UK
Contact:

Re: Drawing lines - BASIC vs machine code

Post by jms2 » Wed Jul 22, 2020 11:19 pm

I have just realised that my previous comment about the VDU23 statements wasn't right - its a semicolon that's missing, not a colon. Hopefully you understood what I was trying to say!

So its VDU 23,1,0;0;0;0;

User avatar
FourthStone
Posts: 1028
Joined: Thu Nov 17, 2016 2:29 am
Location: Brisbane, Australia
Contact:

Re: Drawing lines - BASIC vs machine code

Post by FourthStone » Wed Jul 22, 2020 11:20 pm

Neat game =D> Would have been a great one to type in BITD.

Wondering if you have enough spare cycles to put in a few specs of dirt for even more 3d immersion :-k

Score: 4500

Adam James
Posts: 196
Joined: Tue May 26, 2020 2:32 pm
Contact:

Re: Drawing lines - BASIC vs machine code

Post by Adam James » Thu Jul 23, 2020 12:15 am

jms2 wrote:
Wed Jul 22, 2020 11:19 pm
I have just realised that my previous comment about the VDU23 statements wasn't right - its a semicolon that's missing, not a colon. Hopefully you understood what I was trying to say!

So its VDU 23,1,0;0;0;0;
I figured you meant semicolon yes, as I've noticed similar VDU statements when reading around, though I haven't gone back to change the code yet!

Thank you:)
FourthStone wrote:
Wed Jul 22, 2020 11:20 pm
Neat game =D> Would have been a great one to type in BITD.
Thanks. That's two compliments now from forum members who are clearly very "programmy". To be honest I was dreading posting code I'd written on this forum, but I like the way this has gone so far:)

I think it probably could have made it as a type-in, and to be honest, when I compare it to some of the commercial BBC games I've stumbled across recently, even though they obviously are the result of a huge amount of time, effort and expertise, I've found them less fun to play than this! I guess some concepts just work well for certain types of minds.
FourthStone wrote:
Wed Jul 22, 2020 11:20 pm
Wondering if you have enough spare cycles to put in a few specs of dirt for even more 3d immersion :-k
Given I'm just as happy with 3 poles as 4, I'd say I could sneak something in there while there are 3 poles on the go!

Based on the Ewok comment earlier, which I still haven't deciphered, I did actually think of occasionally dropping an Ewok character onto the ground, but couldn't work out whether you should kill it, absorb it, avoid it, or cuddle it. Maybe dirt is a more sensible idea!
FourthStone wrote:
Wed Jul 22, 2020 11:20 pm
Score: 4500
Not bad... but you can do better! I've got a good mind to nominate this game for a high-score challenge once I've added some secret key presses to it:)

Post Reply

Return to “programming”