8-bit style bouncing ball around a canvas
Bash + Unix utilities, 125 117 bytes
for((x=y=u=v=1;;x+=u,y+=v,u=(x<1||x>=`tput cols`-1)?-u:u,v=(y<1||y>=`tput lines`-1)?-v:v)){
tput cup $y $x
sleep .1
}
Animation of sample run:
CP-1610 assembly, 67 … 64 62 DECLEs = 78 bytes
This code is intended to be run on an Intellivision. It's using one of its hardware sprites, known as a MOB (for Mobile Object).
A CP-1610 opcode is encoded with a 10-bit value, known as a 'DECLE'. This program is 62 DECLEs long, starting at $4800 and ending at $483D.
Hexadecimal dump + source
ROMW 10 ; use 10-bit ROM
ORG $4800 ; start program at address $4800
FRAME EQU $17E ; frame #
;; ------------------------------------------------ ;;
;; main entry point ;;
;; ------------------------------------------------ ;;
main PROC
4800 0001 SDBD ; load Interrupt Service Routine
4801 02B8 002B 0048 MVII #isr, R0 ; into R0
4804 0240 0100 MVO R0, $100 ; update ISR
4806 0040 SWAP R0
4807 0240 0101 MVO R0, $101
4809 02B9 0208 MVII #$0208, R1 ; initialize R1 = X
480B 02BA 0108 MVII #$0108, R2 ; initialize R2 = Y
480D 02BB 0001 MVII #1, R3 ; initialize R3 = DX
480F 009C MOVR R3, R4 ; initialize R4 = DY
4810 0002 EIS ; enable interrupts
;; ------------------------------------------------ ;;
;; main loop ;;
;; ------------------------------------------------ ;;
4811 0280 017E @@loop MVI FRAME, R0 ; R0 = current frame #
4813 0340 017E @@spin CMP FRAME, R0 ; wait for next frame
4815 0224 0003 BEQ @@spin
4817 00D9 ADDR R3, R1 ; X += DX
4818 0379 02A0 CMPI #$2A0, R1 ; reached right border?
481A 0204 0003 BEQ @@updDx
481C 0379 0208 CMPI #$208, R1 ; reached left border?
481E 002F ADCR PC
481F 0023 @@updDx NEGR R3 ; DX = -DX
4820 00E2 ADDR R4, R2 ; Y += DY
4821 037A 0160 CMPI #$160, R2 ; reached bottom border?
4823 0204 0003 BEQ @@updDy
4825 037A 0108 CMPI #$108, R2 ; reached top border?
4827 002F ADCR PC
4828 0024 @@updDy NEGR R4 ; DY = -DY
4829 0220 0019 B @@loop ; loop forever
ENDP
;; ------------------------------------------------ ;;
;; ISR ;;
;; ------------------------------------------------ ;;
isr PROC
482B 01DB CLRR R3 ; clear a bunch of STIC registers
482C 02BC 0020 MVII #$20, R4
482E 0263 @@clear MVO@ R3, R4 ; (including background color,
482F 037C 0032 CMPI #$32, R4 ; border color, etc.)
4831 0226 0004 BLE @@clear
4833 0259 MVO@ R1, R3 ; update X register of MOB #0
4834 0242 0008 MVO R2, $8 ; update Y register of MOB #0
4836 02BB 017E MVII #$017E, R3 ; update A register of MOB #0
4838 0243 0010 MVO R3, $10 ; (using a yellow "O")
483A 0298 MVI@ R3, R0 ; increment frame #
483B 0008 INCR R0
483C 0258 MVO@ R0, R3
483D 00AF JR R5 ; return from ISR
ENDP
Output
HTML (Microsoft Edge/Internet Explorer), 81 bytes
Pretend it's 1998 with these nested <marquee>
tags:
<marquee behavior=alternate direction=down><marquee behavior=alternate width=99>O
Tested in Microsoft Edge, though from what I've read IE should also still support marquees. Decidedly does not work in Chrome.
Setting direction=up
would save 2 bytes, but break the rule that the ball has to start at the top of the canvas.