I am digging in some of my old programs from the eighties. In parallel with BBCBASIC I did a lot of UniComal programming. I did a Lander game and saw that UniComal had a procedures like:
loadscreen("picture.pic")
and of course a savescreen.
getshape(xmin, xmax, ymin, ymax, drawing$)
and
putshape(xmin, xmax, ymin, ymax, drawing$)
Do we have something like these procedures or similar in BBCBASIC?
Retro nostalgia
-
- Posts: 127
- Joined: Tue 07 May 2019, 16:47
Retro nostalgia
You do not have the required permissions to view the files attached to this post.
Last edited by Ivan on Sat 06 Feb 2021, 13:41, edited 1 time in total.
BBC Model B - 1984-1989. 6502 assembler, Unicomal 1988-1994, Some C and C++, Pascal 1990-1994. Bought a copy of BBC-BASIC 2007, but started to program at a daily basis 2019. C++ in 2021.
Re: Retro nostalgia
Yes, indeed. Have a look *DISPLAY and *SCREENSAVE, for a start, which will load a picture from memory and display it, and save (a part of) the screen as a bitmap file. You can also use *LOAD to load a file into memory, and then *MDISPLAY to plot it, which might be better if you need a lot of speed, and/or to draw the same thing multiple times.
One nice thing you could also look at is using RECTANGLE TO and RECTANGLE FILL. If you make the graphics window bigger than the visible window you can draw things "offscreen", and copy them into view when you want them.
...but for simple things, it may be fine just to draw them on the fly - that's what I did when David Williams issued a challenge on a moonlander game (forgot the original name). I think David posted one too. I can't track it down, so I'll paste a copy here in case you are interested:
This version is mouse driven: move the mouse to rotate the spaceship, and press left button to fire the engine. Land on the green pad going slow enough...
Feel free to develop your own levels!
One nice thing you could also look at is using RECTANGLE TO and RECTANGLE FILL. If you make the graphics window bigger than the visible window you can draw things "offscreen", and copy them into view when you want them.
...but for simple things, it may be fine just to draw them on the fly - that's what I did when David Williams issued a challenge on a moonlander game (forgot the original name). I think David posted one too. I can't track it down, so I'll paste a copy here in case you are interested:
Code: Select all
MODE 8
xRes%=@vdu%!208 :REM Window width in pixels. There are 2 BB4W graphics units per pixel, so as a coordinate it represents the centre of the window
yRes%=@vdu%!212
numPoints%=3 :REM Number of points in the lander - could draw a fancier lander if you wanted to
DIM sS(numPoints%-1,1)
FOR x%=0 TO numPoints%-1
READ sS(x%,0),sS(x%,1)
NEXT x%
DATA 10,0,0,30,-10,0 :REM Coordinates for the drawing of the lander
g=9.8 :REM Acceleration due to gravity
m=10000 :REM Mass of basic lander (fuel added to affect acceleration)
Level%=1 :REM Starting level.If you are developing a new level, set this to your level number,to save having to fly through the earlier ones!
maxLevel%=7
Score%=0
Lives%=3
COLOUR 11 :REM Set text colour to yellow for showing score etc: Won't crash lander!
REPEAT
REM Choose and draw the level. Also sets initial position, velocity and fuel level, as well as landing pad size and position
CASE Level% OF
WHEN 1:PROCLevel1
WHEN 2:PROCCrevasse
WHEN 3:PROCLevel3
WHEN 4:PROCRings
WHEN 5:PROCTunnel1
WHEN 6:PROCTunnel2
WHEN 7:PROCMaze
ENDCASE
doneLevel%=FALSE
*REFRESH OFF
MOUSE OFF :REM Hides mouse pointer, to make it less distracting - but risk you'll click outside the window, hide it, and crash!
MOUSE TO xRes%,yRes% :REM Centres the mouse on the window. Moving it left or right will tilt the lander
Contact%=FALSE :REM We haven't hit anything (yet)
REPEAT
MOUSE mx%,my%,mz%
IF INKEY(-10) THEN t=5 ELSE t=0 :REM Thrust (engine on if left mouse button pressed)
F-=t :REM Use up some fuel
IF F<t THEN F=0:t=0 :REM If we've run out, we can't run the engine...
IF t THEN SOUND &11,-15,32,1 :REM Make a sound to indicate that engine is on
IF Contact% THEN PROCTest :REM Check whether we had hit anything last time lander was drawn, and if so, what
Angle=(xRes%-mx%)*PI/640 :REM Calculate angle of lander, depending on where the mouse is relative to the centre of the window
vY+=t*COS(Angle)*100/(m+F)-g/1000 :REM Adjust vertical velocity according to gravity and thrust
vX-=t*SIN(Angle)*100/(m+F) :REM Adjust horizontal velocity according to thrust
pX+=vX :REM Adjust coordinates of the lander according to velocity vectors
pY+=vY
IF pX<-10 THEN pX+=2*xRes% :REM Wrap window - you can fly off the edge horizontally and appear on the other side!
IF pX>2*xRes%+10 THEN pX-=2*xRes%
PROCDrawSpaceship(pX,pY,Angle,t) :REM Draw the lander in its (new) position
PRINT TAB(65,0),"Score: "+STR$(Score%)
PRINT TAB(65,1),"Lives: "+STR$(Lives%)
PRINT TAB(65,2),"Level: "+STR$(Level%)
PRINT TAB(65,3),"Fuel: "+STR$(F)+" "
*REFRESH
WAIT 2
PROCDrawSpaceship(pX,pY,Angle,t) :REM *UN*-draw the lander (by XOR plotting it over itself). Since REFRESH is off, we never see this,but it clears things before the new plot
UNTIL doneLevel% :REM Landed or crashed!
UNTIL Level%=maxLevel%+1 OR Lives%=0
*REFRESH ON
*MOUSE ON
PROCMessage("Your final score was "+STR$(Score%),"Lander")
REM SYS "MessageBox", @hwnd%, "Your final score was "+STR$(Score%), "Lander", 0
QUIT
:
DEFPROCDrawSpaceship(px,py,a,t)
LOCAL x%,tx%,ty%
GCOL 3,15 :REM Note the use of XOR plotting mode (3) - if we redraw with the same parameters it rubs out the lander!
MOVE px,py :REM Move to defining point of the lander (centre bottom)
FOR x%=0 TO numPoints%-1
tx%=px+sS(x%,0)*COS(a)-sS(x%,1)*SIN(a) :REM Calculate coordinates of each point, bearing in mind offset and angle
ty%=py+sS(x%,0)*SIN(a)+sS(x%,1)*COS(a)
IF POINT(tx%,ty%)<>0 THEN Contact%=POINT(tx%,ty%) :REM Test if any of the vertices coincide with the scenery.... at least, grey or green bits of it
DRAW tx%,ty%
NEXT x%
DRAW px,py :REM Close shape (could fill it, I guess, if you wanted to!)
IF t THEN
REM Engine is on: draw a red rocket flare!
GCOL 3,1
DRAW px+10*SIN(a),py-10*COS(a)
ENDIF
ENDPROC
:
DEFPROCTest
LOCAL sc%
REM Note that this only has an effect if the colour hit was 7 or 2 - so you could draw stars (or text) in other colours, and they wouldn't crash the lander
CASE Contact% OF
WHEN 7:
REM Crash! We've hit the landscape
PROCMessage("Oops! You crashed!","Lander (didn't)")
REM SYS "MessageBox", @hwnd%, "Oops! You crashed!", "Lander (didn't)", 0
Lives%-=1
doneLevel%=TRUE
WHEN 2:
REM On landing pad!
IF ABS(vX)<1 AND ABS(vY)<1 AND ABS(Angle)<0.5 THEN
REM Not going too fast, or tipped over too much
sc%=F+(TargetW%/2-ABS(pX-TargetX%))*100+(5000-3000*ABS(vY))+(5000-5000*ABS(Angle))
PROCMessage("Congratulations! "+"You scored "+STR$(sc%),"Lander")
REM SYS "MessageBox", @hwnd%, "Congratulations!"+CHR$(13)+CHR$(10)+"You scored "+STR$(sc%), "Lander", 0
Score%+=sc%
Level%+=1
doneLevel%=TRUE
ELSE
REM We WERE going too fast, or tipped over too much
PROCMessage("Oops! You crashed!","Lander (didn't)")
REM SYS "MessageBox", @hwnd%, "Oops! You crashed!", "Lander (didn't)", 0
Lives%-=1
doneLevel%=TRUE
ENDIF
ENDCASE
Contact%=FALSE
ENDPROC
:
DEFPROCMessage(m$,h$)
LOCAL x%,y%,z%,done%
done%=FALSE
GCOL 0,0
RECTANGLE FILL xRes%/2,yRes%/2,xRes%,yRes%
GCOL 0,15
RECTANGLE xRes%/2,yRes%/2,xRes%,yRes%
VDU 5
GCOL 0,3
MOVE xRes%/2+5,yRes%*3/2-5
PRINT h$
MOVE xRes%-@vdu%!216*LEN(m$),yRes%+@vdu%!220
PRINT m$
MOVE xRes%-2*@vdu%!216,yRes%/2+2*@vdu%!220+25
PRINT "OK"
GCOL 0,15
RECTANGLE xRes%-2*@vdu%!216-10,yRes%/2+20,4*(@vdu%!216)+20,2*@vdu%!220+30
*REFRESH ON
MOUSE ON
REPEAT
MOUSE x%,y%,z%
WAIT 1
IF z%>0 THEN IF x%>xRes%-2*@vdu%!216-10 AND x%<xRes%+2*@vdu%!216+10 AND y%>yRes%/2+20 AND y%<yRes%/2+2*@vdu%!220+50 THEN done%=TRUE
UNTIL done%
REPEAT MOUSE x%,y%,z% UNTIL z%=0
VDU 4
MOUSE OFF
*REFRESH OFF
ENDPROC
:
REM Here are the definitions for the different levels. Basically you need to define a landscape where Colour 7 defines things you can't hit
REM and Colour 2 defines the landing area(s). I've assumed that open space is black, but it doesn't need to be
REM - though you'll need to be careful with the flood fills if you draw in different colours!
REM I've used some different approaches to drawing the landscape - see what you like.
DEFPROCLevel1
CLS
GCOL 0,7 :REM Absolute colour plotted - use colour 7 (grey by default, but you could change that if you wanted a moon made of green cheese...)
MOVE 0,20
DRAW 300,50
DRAW 400,100
DRAW 600,40
DRAW 800,40
DRAW 900,100
DRAW 1000,80
DRAW 1050,120
DRAW 1100,60
DRAW 1280,80
PLOT 141,10,10 :REM Flood fill
GCOL 0,2 :REM Change to colour 2 to indicate landing pad - again you could reprogram colour 2 if you wanted to (for example, if you made colour 7 into green...)
TargetX%=700 :REM Define target location and width - needed elsewhere to calculate score, which depends on how close you are to the centre
TargetW%=160
RECTANGLE FILL TargetX%-TargetW%/2,32,160,8
pX=100 :REM Set initial coordinates of the lander, and its velocity vectors
pY=2*yRes%-100
vX=0
vY=0
F=5000 :REM Fuel load -affects performance (heavy landers accelerate slower), or you could use it to make it more difficult!
ENDPROC
:
DEFPROCCrevasse
CLS
GCOL 0,7
MOVE 0,200
DRAW 300,350
DRAW 400,200
DRAW 550,700
DRAW 600,600
DRAW 620,40
DRAW 820,40
DRAW 900,650
DRAW 1000,400
DRAW 1050,120
DRAW 1100,260
DRAW 1280,380
PLOT 141,10,10
GCOL 0,2
TargetX%=700
TargetW%=120
RECTANGLE FILL TargetX%-TargetW%/2,32,160,8
pX=100
pY=2*yRes%-100
vX=0
vY=0
F=5000
ENDPROC
:
DEFPROCLevel3
CLS
GCOL 0,7
MOVE 0,100
DRAW 200,250
DRAW 300,400
DRAW 550,700
DRAW 700,600
DRAW 650,500
DRAW 450,200
DRAW 500,100
DRAW 520,40
DRAW 720,40
DRAW 900,500
DRAW 800,700
DRAW 900,750
DRAW 1050,520
DRAW 1100,360
DRAW 1280,380
PLOT 141,10,10
GCOL 0,2
TargetX%=600
TargetW%=120
RECTANGLE FILL TargetX%-TargetW%/2,32,160,8
pX=100
pY=2*yRes%-100
vX=0
vY=0
F=5000
ENDPROC
:
DEFPROCRings
CLS
GCOL 0,7
CIRCLE FILL 300,600,300
CIRCLE FILL 900,400,300
GCOL 0,0
CIRCLE FILL 300,600,200
CIRCLE FILL 900,400,200
RECTANGLE FILL 400,650,250,100
RECTANGLE FILL 800,550,100,300
GCOL 0,2
TargetX%=950
TargetW%=160
RECTANGLE FILL TargetX%-TargetW%/2,300,TargetW%,8
pX=300
pY=600
vX=0
vY=0
F=5000
ENDPROC
:
DEFPROCTunnel1
LOCAL x%,y%,a%
LOCAL DATA :REM Store the existing data pointer, so we can move it here
RESTORE +1 :REM Start reading data from the next line
DATA 0,600,200,650,800,620,850,600,800,500,650,450,150,300,50,100,120,50,420,40,600,50
DATA 900,40,1100,40,1150,80,1100,160,880,180,280,200,300,230,550,250,950,420,1280,920
CLS
GCOL 0,7
READ x%,y%
MOVE x%,y%
REM Rather than a whole string of draw commands, read and plot them in a loop
FOR a%=1 TO 20
READ x%,y%
DRAW x%,y%
NEXT a%
RESTORE DATA :REM Put the old data pointer back in place
PLOT 141,10,10
GCOL 0,2
TargetX%=1000
TargetW%=120
RECTANGLE FILL TargetX%-TargetW%/2,32,160,8
pX=100
pY=2*yRes%-100
vX=0
vY=0
F=5000
ENDPROC
:
DEFPROCTunnel2
LOCAL x%,y%,a%
LOCAL DATA :REM Store the existing data pointer, so we can move it here
RESTORE +1 :REM Start reading data from the next line
DATA 0,200,100,50,200,20,450,70,800,100,1200,150,1250,400,1200,900,1100,950,650,700,350,500,700,450,950,450
DATA 980,540,600,560,1000,740,1050,700,950,360,480,280,280,200,300,500,550,750,850,920,900,1024
CLS
GCOL 0,7
READ x%,y%
MOVE x%,y%
REM Rather than a whole string of draw commands, read and plot them in a loop
FOR a%=1 TO 23
READ x%,y%
DRAW x%,y%
NEXT a%
RESTORE DATA :REM Put the old data pointer back in place
PLOT 141,10,10
GCOL 0,2
TargetX%=840
TargetW%=120
RECTANGLE FILL TargetX%-TargetW%/2,450,TargetW%,8
pX=100
pY=2*yRes%-100
vX=0
vY=0
F=5000
ENDPROC
:
DEFPROCMaze
LOCAL x%,y%,r%
x%=500
y%=500
r%=500
CLS
GCOL 0,7
CIRCLE FILL x%,y%,r%
GCOL 0,0
CIRCLE FILL x%,y%,r%-50
GCOL 0,7
CIRCLE FILL x%,y%,r%-150
GCOL 0,0
CIRCLE FILL x%,y%,r%-200
GCOL 0,7
CIRCLE FILL x%,y%,r%-300
GCOL 0,0
CIRCLE FILL x%,y%,r%-350
RECTANGLE FILL x%+130,y%-50,80,50
RECTANGLE FILL x%-295,y%,-60,50
RECTANGLE FILL x%+430,y%+50,80,50
TargetX%=1150
TargetW%=120
GCOL 0,2
RECTANGLE FILL TargetX%-TargetW%/2,250,TargetW%,8
pX=x%
pY=y%
vX=0
vY=0
F=5000
ENDPROC
Feel free to develop your own levels!
-
- Posts: 127
- Joined: Tue 07 May 2019, 16:47
Re: Retro nostalgia
Thanks.
I used a parable to simulate movements.
I used a parable to simulate movements.
BBC Model B - 1984-1989. 6502 assembler, Unicomal 1988-1994, Some C and C++, Pascal 1990-1994. Bought a copy of BBC-BASIC 2007, but started to program at a daily basis 2019. C++ in 2021.