prog8/examples/c64/balloonflight.p8

211 lines
7.8 KiB
Plaintext
Raw Normal View History

%import syslib
%import textio
%import math
2020-03-28 16:06:17 +00:00
2024-10-12 20:30:18 +00:00
; C64 version of a balloon sprites flying over a mountain landscape.
; There is also a X16 version of this in the examples.
2020-12-14 20:57:16 +00:00
2020-03-28 16:06:17 +00:00
main {
2024-09-22 10:20:28 +00:00
bool do_char_scroll = false
2020-03-28 16:06:17 +00:00
sub start() {
2024-09-22 10:20:28 +00:00
uword moon_x = 310
c64.set_sprite_ptr(0, $0f00) ; alternatively, set directly: c64.SPRPTR[0] = $0f00 / 64
2024-09-22 10:20:28 +00:00
c64.set_sprite_ptr(1, $0f00+64) ; alternatively, set directly: c64.SPRPTR[0] = $0f00 / 64
c64.SPENA = %00000011
2020-03-28 16:06:17 +00:00
c64.SP0COL = 14
2024-09-22 10:20:28 +00:00
c64.SP1COL = 7
2020-03-28 16:06:17 +00:00
c64.SPXY[0] = 80
c64.SPXY[1] = 100
2024-09-22 10:20:28 +00:00
set_moon_pos(moon_x)
2020-03-28 16:06:17 +00:00
c64.SCROLX &= %11110111 ; 38 column mode
2024-09-22 10:20:28 +00:00
sys.set_rasterirq(&irq.irqhandler, 250) ; enable animation via raster interrupt
2020-03-28 16:06:17 +00:00
ubyte target_height = 10
2024-09-22 10:20:28 +00:00
ubyte active_height = 25
bool upwards = true
2020-03-28 16:06:17 +00:00
repeat {
2020-03-28 16:06:17 +00:00
ubyte mountain = 223 ; slope upwards
if active_height < target_height {
active_height++
upwards = true
} else if active_height > target_height {
mountain = 233 ; slope downwards
active_height--
upwards = false
} else {
2024-09-22 10:20:28 +00:00
; determine new height for next mountain
2024-10-12 20:30:18 +00:00
ubyte old_height = target_height
if upwards {
2020-03-28 16:06:17 +00:00
mountain = 233
2024-10-12 20:30:18 +00:00
while target_height >= old_height
target_height = 9 + math.rnd() % 15
} else {
2020-03-28 16:06:17 +00:00
mountain = 223
2024-10-12 20:30:18 +00:00
while target_height <= old_height
target_height = 9 + math.rnd() % 15
}
2020-03-28 16:06:17 +00:00
}
2024-09-22 10:20:28 +00:00
while not do_char_scroll {
2020-03-28 16:06:17 +00:00
; let the raster irq do its timing job
}
2024-09-22 10:20:28 +00:00
do_char_scroll = false
scroll_characters_left()
2020-09-27 11:31:46 +00:00
2024-09-22 10:20:28 +00:00
; float the balloon and the moon sprites
if math.rnd() & 1 !=0
2020-03-28 16:06:17 +00:00
c64.SPXY[1] ++
else
c64.SPXY[1] --
2024-09-22 10:20:28 +00:00
moon_x--
if msb(moon_x)==255
moon_x = 340
set_moon_pos(moon_x)
; draw new mountain etc.
const ubyte RIGHT_COLUMN = 39
2020-03-28 16:06:17 +00:00
ubyte yy
for yy in 0 to active_height-1 {
2024-09-22 10:20:28 +00:00
txt.setcc(RIGHT_COLUMN, yy, 32, 2) ; clear top of screen
2020-03-28 16:06:17 +00:00
}
2024-09-22 10:20:28 +00:00
txt.setcc(RIGHT_COLUMN, active_height, mountain, 8) ; mountain edge
2020-03-28 16:06:17 +00:00
for yy in active_height+1 to 24 {
2024-09-22 10:20:28 +00:00
txt.setcc(RIGHT_COLUMN, yy, 160, 8) ; draw filled mountain
2020-03-28 16:06:17 +00:00
}
2024-09-22 10:20:28 +00:00
ubyte clutter = math.rnd()
if clutter > 100 {
2020-03-28 16:06:17 +00:00
; draw a star
2024-09-22 10:20:28 +00:00
txt.setcc(RIGHT_COLUMN, clutter % (active_height-1), sc:'.', math.rnd())
2020-03-28 16:06:17 +00:00
}
2024-09-22 10:20:28 +00:00
if clutter > 200 {
2020-03-28 16:06:17 +00:00
; draw a tree
2024-09-22 10:20:28 +00:00
ubyte tree = sc:'↑'
2020-03-28 16:06:17 +00:00
ubyte treecolor = 5
2024-09-22 10:20:28 +00:00
if clutter & %00010000 != 0
tree = sc:'♣'
else if clutter & %00100000 != 0
tree = sc:'♠'
if math.rnd() > 130
2020-03-28 16:06:17 +00:00
treecolor = 13
2024-09-22 10:20:28 +00:00
txt.setcc(RIGHT_COLUMN, active_height, tree, treecolor)
2020-03-28 16:06:17 +00:00
}
2024-09-22 10:20:28 +00:00
if clutter > 235 {
2020-03-28 16:06:17 +00:00
; draw a camel
2024-09-22 10:20:28 +00:00
txt.setcc(RIGHT_COLUMN, active_height, sc:'π', 9)
2020-03-28 16:06:17 +00:00
}
}
}
2024-09-22 10:20:28 +00:00
sub set_moon_pos(uword x) {
c64.SPXY[2] = lsb(x)
c64.SPXY[3] = 55
if msb(x)!=0
c64.MSIGX |= %00000010
else
c64.MSIGX &= %11111101
}
sub scroll_characters_left () {
; Scroll the bottom half (approx.) of the character screen 1 character to the left
; contents of the rightmost column are unchanged, you should clear/refill this yourself
; Without clever split-screen tricks, the C64 is not fast enough to scroll the whole
; screen smootly without tearing. So for simplicity it's constrained to less rows
; such that what is scrolled, *does* scrolls smoothly.
; For maximum performance the scrolling is done in unrolled assembly code.
%asm {{
ldx #0
ldy #38
-
.for row=10, row<=24, row+=1
lda cbm.Screen + 40*row + 1,x
sta cbm.Screen + 40*row + 0,x
lda cbm.Colors + 40*row + 1,x
sta cbm.Colors + 40*row + 0,x
.next
inx
dey
bpl -
rts
}}
}
}
irq {
; does the smooth scrolling immediately after the visible screen area,
; so there is no screen tearing. The main loop does the "big" character
; scrolling when the soft-scroll runs out after 8 pixels
ubyte smoothx=0
sub irqhandler() -> bool {
smoothx = (smoothx-1) & 7
main.do_char_scroll = smoothx==7
c64.SCROLX = (c64.SCROLX & %11111000) | smoothx
return false
}
2020-03-28 16:06:17 +00:00
}
spritedata $0f00 {
2024-09-22 10:20:28 +00:00
; this memory block contains the sprite data. it must start on an address aligned to 64 bytes.
; for simplicity, it's currently statically located at $0f00 (not far in memory after the program code),
; but there are ways to do this more dynamically.
2020-03-28 16:06:17 +00:00
%option force_output ; make sure the data in this block appears in the resulting program
ubyte[] balloonsprite = [ %00000000,%01111111,%00000000,
%00000001,%11111111,%11000000,
%00000011,%11111111,%11100000,
%00000011,%11100011,%11100000,
%00000111,%11011100,%11110000,
%00000111,%11011101,%11110000,
%00000111,%11011100,%11110000,
%00000011,%11100011,%11100000,
%00000011,%11111111,%11100000,
%00000011,%11111111,%11100000,
%00000010,%11111111,%10100000,
%00000001,%01111111,%01000000,
%00000001,%00111110,%01000000,
%00000000,%10011100,%10000000,
%00000000,%10011100,%10000000,
%00000000,%01001001,%00000000,
%00000000,%01001001,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
%00000000,%00111110,%00000000,
2024-09-22 10:20:28 +00:00
%00000000,%00011100,%00000000,
0]
ubyte[] moonsprite = [ %00000000,%00000110,%00000000,
%00000000,%00011100,%00000000,
%00000000,%01111000,%00000000,
%00000000,%11111000,%00000000,
%00000001,%11110000,%00000000,
%00000011,%11110000,%00000000,
%00000011,%11110000,%00000000,
%00000111,%11100000,%00000000,
%00000111,%11100000,%00000000,
%00000111,%11100000,%00000000,
%00000111,%11100000,%00000000,
%00000111,%11100000,%00000000,
%00000111,%11100000,%00000000,
%00000111,%11100000,%00000000,
%00000011,%11110000,%00000000,
%00000011,%11110000,%00000000,
%00000001,%11110000,%00000000,
%00000000,%11111000,%00000000,
%00000000,%01111000,%00000000,
%00000000,%00011100,%00000000,
%00000000,%00000110,%00000000,
0]
2020-03-28 16:06:17 +00:00
}