Help making a basic game for CoCo 2

This forum is dedicated to those who want support programming in ugBASIC.
Questo forum è dedicato a chi desidera supporto per programmare in ugBASIC.
Ce forum est dédié à ceux qui souhaitent prendre en charge la programmation en ugBASIC.
Post Reply
User avatar
Giovani_Gualdi
Posts: 6
Joined: Wed Mar 05, 2025 6:34 pm

Help making a basic game for CoCo 2

Post by Giovani_Gualdi »

Hi! I've been diving into ugBasic's settings, especially looking at the useful examples posted by spotlessmind1975, ericomont, and others, and I'm seriously impressed with the performance. I'm planning to build a simple 'destroy everything that moves' style game, and use it to get better at basic routines like movement, collisions, shooting, multitasking without lag, and all that stuff.
So, I whipped up some movement and joystick control routines, and they're working, check it out:

Code: Select all

SCREEN #14                                              :'PMODE 4 (screen mode)
COLOR #0,#5                                             :'inverts the screen colors
CLS BLACK                                               :'clears the screen (black)

'Variables                                         
VAR x,y AS BYTE:x=(WIDTH/2)-8:y=(HEIGHT/2)-8            :'ship initial position
VAR xa,ya AS BYTE:xa=0:ya=0                             :'enemy ship position (RND)
VAR xl,yl AS BYTE:xl=0:yl=0                             :'shot position
GLOBAL x,y,xl,yl,xa,ya                                  :'declare variables as global
GLOBAL ship,enemyShip,background                        :'makes image variables global


'Images                             
background := NEW IMAGE (16,16)                         :'creates background image 16x16
ship := LOAD IMAGE ("ship.png")                         :'loads player ship image
enemyShip := LOAD IMAGE ("enemyship.png")               :'loads enemy ship image

GET IMAGE background FROM 0,0                           :'captures part of the background

'======DEFINE PROCEDURES======     

'Activate player movement                     
PROCEDURE movement   
    IF JRIGHT(0) AND x<215 THEN:                        :'if right joystick and ship not at right edge:
        PUT IMAGE background AT (x-16),y                :'redraws background behind ship
        INC x                                           :'moves ship right
    ENDIF

    IF JLEFT(0) AND x>25 THEN:                          :'if left joystick and ship not at left edge:
        PUT IMAGE background AT (x+16),y                :'redraws background behind ship
        DEC x                                           :'moves ship left
    ENDIF

    IF JUP(0) AND y>35 THEN:                            :'if up joystick and ship not at top edge:
        PUT IMAGE background AT x,(y+16)                :'redraws background behind ship
        DEC y                                           :'moves ship up
    ENDIF

    IF JDOWN(0) AND y<145 THEN:                         :'if down joystick and ship not at bottom edge:
        PUT IMAGE background AT x,(y-16)                :'redraws background behind ship
        INC y                                           :'moves ship down
    ENDIF
END PROC        

'Repositions the enemy ship on the screen in a random position-y
PROCEDURE reloadEnemyShipPosition                           
    xa=240                                              :'sets x position to right edge
    ya=RND(180)+10                                      :'sets random y position
END PROC                                             

'Enemy ship movement                     
PROCEDURE  moveEnemyShip                               
    ADD xa,(-1)                                         :'move enemy ship left
    PUT IMAGE background AT (xa+16),ya                  :'redraws background behind ship
    PUT IMAGE enemyShip AT xa, ya                       :'draws enemy ship at new position
    IF xa <= 10 THEN:                                   :'if enemy ship at left edge:
        xa=10:PUT IMAGE background AT xa,ya             :'reset ship and background
        reloadEnemyShipPosition[]
    ENDIF
END PROC                                                 

reloadEnemyShipPosition[]

'=========MAIN LOOP===========
DO                                                      :'start of main game loop
    PUT IMAGE ship AT x, y                              :'draws player ship at current position                               
    movement[]                                          :'calls movement procedure
    moveEnemyShip[]                                     :'calls enemy ship movement procedure
LOOP                                                    :'end of main loop

However, I'd like to smooth out the horizontal movement to be more like the vertical movement, it's so smooth. Is there any way to get around this?

Required images
Image
Image
Last edited by Giovani_Gualdi on Fri Mar 07, 2025 1:29 pm, edited 3 times in total.
spotlessmind1975
Site Admin
Posts: 204
Joined: Fri Oct 06, 2023 8:25 pm

Re: Help making a basic game for CoCo 2

Post by spotlessmind1975 »

Hi Giovani_Gualdi, and welcome!
Giovani_Gualdi wrote: Thu Mar 06, 2025 2:43 am However, I'd like to smooth out the horizontal movement to be more like the vertical movement, it's so smooth. Is there any way to get around this?
First of all thank you very much for the code, really interesting! Reading the code, I see that you use the PUT IMAGE instruction. This instruction tries to draw the image you gave it as input in the shortest time possible. To do this, it uses, as far as technically possible, the alignment of the pixels to the byte.

In fact, the majority of current 8-bit computer video chipsets map two or more pixels to the same byte. It follows that it is not possible to draw an image with an offset of (for example) a single pixel because it would mean performing a "shift" within the byte. Instead, PUT IMAGE copies the bytes in such a way as to make the starting image coincide with the target image.

For example, on the Motorola 6847 with 4-color graphics mode you have 4 pixels for each byte (2 bits per pixel, 8 bits per byte, 4 pixels per byte). Therefore, it is possible to draw an image at coordinate 0, then at 4, then at 8, and so on. ugBASIC already makes the necessary adjustments during the drawing phase, if this number is not a multiple of 4, to make it so.

If you wanted to draw an image starting from position 3, it would be necessary to make 3 shifts to the right of the image bitmap and then draw it with PUT IMAGE at position 0. Unfortunately, this is a rather slow operation, and therefore it is not implemented automatically. You can however take advantage of the possibility of loading an image and having ugBASIC generate a series of intermediate images with just a one pixel offset, and then drawing them "in place", to emulate one pixel movement.

This is a feature available with the LOAD ATLAS command and the ROLL X option. If you want to know more, the syntax is described in chapters 6.4 Loading atlas and 17.344 LOAD ATLAS of the user manual, and if you need more help or support we can move to the Support area.

Thank you again!
User avatar
Giovani_Gualdi
Posts: 6
Joined: Wed Mar 05, 2025 6:34 pm

Re: Help making a basic game for CoCo 2

Post by Giovani_Gualdi »

Spotlessmind1975, thank you so much for such valuable elucidations, I wasn't aware of these details. UgBasic is truly wonderful and vast, offering effective solutions. I will study the LOAD ATLAS and ROLL X commands more carefully, and try to implement what I intend. And... yes, I would very much like this topic to move to the support area, because, in addition to these questions, I have others that I would like to ask.
User avatar
ericomont
Posts: 29
Joined: Sun Oct 08, 2023 11:31 am

Re: Help making a basic game for CoCo 2

Post by ericomont »

Hi Giovani,
Blitting at the byte border is the fastest possible way, as Marco said. Same thing happens in DECB with GET/PUT commands, if you mess with the G parameter it will only PUT on byte border and you get a speed increase.

Anyways, in ugBasic, adding extra frames is the best to keep the speed up, will cost some memory, or you can bit shift in real time, which will cost performance and is hard to code on the 4 color resolutions. These are edge solutions, there are many others in between depending on the need.

In your case I take the performance is a must, so adding frames would be the choice.
PMODE 4 256x192 (2colors) has the byte border at every 8 pixels horizontally.
This means having 8 frames for an image to move per pixel.

If you are on NTSC and using artifact colors, your horizontal positions must happen every 2 pixels.
So here only 4 frames are needed.

I prefer to create those frames myself, gives more control on positioning.
A simple way to do it is to center your image on the byte border frame and when the image hits the border, move the frame a byte.
Here is a visual example, grid is the byte border, I used 4 frames:
Image

Back on your case.
Remember that in-code, you will have to move things accounting to that, so your PUT command will hang on its X position and your frame count will advance till the X then moves 8 pixels. In general, moving things sideways will involve PUT and a counter to choose which frame to use.
I will do an example as time allow.

Also, moving topic to the SUPPORT would be better I think.
User avatar
ericomont
Posts: 29
Joined: Sun Oct 08, 2023 11:31 am

Re: Help making a basic game for CoCo 2

Post by ericomont »

Hello back Giovanni,
I made a post on the Snippet session with an example.
It bounces a little ball around the screen in pmode 4 artifact colors.

viewtopic.php?p=364#p364

It should help you doing the pixel perfect motion.
Also, I can't see your posted images.
User avatar
Giovani_Gualdi
Posts: 6
Joined: Wed Mar 05, 2025 6:34 pm

Re: Help making a basic game for CoCo 2

Post by Giovani_Gualdi »

Wow, thanks Erico! I'll take a look there.
Also, I can't see your posted images.
Ok, I'll fix that.
User avatar
Giovani_Gualdi
Posts: 6
Joined: Wed Mar 05, 2025 6:34 pm

Re: Help making a basic game for CoCo 2

Post by Giovani_Gualdi »

Hi! After studying the content sent by ericomont ( viewtopic.php?p=364#p364 ) and spotlessmind1975, I adjusted my routines, and now they are more enjoyable to play, here is the code:

Code: Select all

'------------------------------------------'
'Simple CoCoGame   - v1.2
'By Giovani Gualdi - 2025
'------------------------------------------'
SCREEN #14 :COLOR #0,#5 :CLS 0     

DIM x(2):DIM y(2)								
DIM xs(2):DIM ys(2) 								
DIM f(2) 

x(0)=128 :y(0)=96          :f(0)=0 :xs(0)=1:ys(0)=2
x(1)=232 :y(1)=RND(162)+10 :f(1)=4 :xs(1)=1:ys(1)=2
                                     
ship :=LOAD ATLAS ("sqr3.png") FRAME SIZE (24,16)                
background :=NEW IMAGE (24,16) 
GET IMAGE background FROM 0,0

GLOBAL x,y,xs,ys,f,ship,background                               

PROCEDURE movementShip 
    PUT IMAGE  ship FRAME f(0) AT x(0),y(0)			        
    IF JRIGHT(0) AND x(0)<232 THEN:                        
        f(0)=f(0)+xs(0)						               
        IF f(0)=4 THEN :f(0)=0 :x(0)=x(0)+8 :ENDIF
    ENDIF
    IF JLEFT(0) AND x(0)>10 THEN:                          
        f(0)=f(0)-xs(0)	
        IF f(0)=-1 THEN :f(0)=3 :x(0)=x(0)-8 :ENDIF			
    ENDIF
    IF JUP(0) AND y(0)>10 THEN:                            
        y(0)=y(0)-ys(0)
    ENDIF
    IF JDOWN(0) AND y(0)<172 THEN:                         
        y(0)=y(0)+ys(0)
    ENDIF
END PROC        

PROCEDURE enemyShip
    PUT BITMAP ship FRAME f(1) AT x(1),y(1)			
    f(1)=f(1)-xs(1)				                    
    IF f(1)=3 THEN :f(1)=7 :x(1)=x(1)-8 :ENDIF			
    IF f(1)=4 AND x(1)=0 THEN:
        PUT IMAGE background AT x(1),y(1)
	x(1)=232 :y(1)=RND(115)+35 			
    ENDIF
    WAIT 25 MS
END PROC  

BEGIN GAMELOOP
    movementShip[]
    enemyShip[]
END GAMELOOP
spotlessmind1975, I couldn't get LOAD ATLAS with ROLL XY to work, I needed more details on how to proceed, or, who knows, when you have some time, a small example too..


Image
User avatar
Giovani_Gualdi
Posts: 6
Joined: Wed Mar 05, 2025 6:34 pm

Re: Help making a basic game for CoCo 2

Post by Giovani_Gualdi »

Hi everyone! Here's another part of the space saga :)
Now I've added shooting for the ship and three random speeds (1,2 or 3) for the enemy ship.
Here's the code:

Code: Select all

'------------------------------------------'
'Simple CoCoGame   - v1.3
'By Giovani Gualdi - 2025
'------------------------------------------'
SCREEN #14  :COLOR #0,#5    :CLS 0  

GLOBAL

DIM x(3)    :DIM y(3)								
DIM xs(3)   :DIM ys(3) 								
DIM f(2) 

v=(BYTE)1
VAR z AS BYTE

fr=(BYTE)0

x(0)=128 :y(0)=96           :f(0)=0     :xs(0)=1:ys(0)=2
x(1)=232 :y(1)=RND(162)+10  :f(1)=4     :xs(1)=1:ys(1)=2
x(2)=x(0):y(2)=y(0)         

ship :=LOAD ATLAS ("sqr3.png") FRAME SIZE (24,16)     
laser := LOAD IMAGE ("laser.png")  
background := NEW IMAGE (16,16):GET IMAGE background FROM 0,0

PROCEDURE movementShip 
    PUT IMAGE  ship FRAME f(0) AT x(0),y(0)			        
    IF JRIGHT(0) AND x(0)<216-24 THEN:                        
        f(0)=f(0)+xs(0)						               
        IF f(0)=4 THEN :f(0)=0 :x(0)=x(0)+8 :ENDIF
    ENDIF
    IF JLEFT(0) AND x(0)>10 THEN:                          
        f(0)=f(0)-xs(0)	
        IF f(0)=-1 THEN :f(0)=3 :x(0)=x(0)-8 :ENDIF			
    ENDIF
    IF JUP(0) AND y(0)>10 THEN:                            
        y(0)=y(0)-ys(0)
    ENDIF
    IF JDOWN(0) AND y(0)<172 THEN:                         
        y(0)=y(0)+ys(0)
    ENDIF
END PROC        

PROCEDURE enemyShip   
    PUT BITMAP ship FRAME f(1) AT x(1),y(1)			
    f(1)=f(1)-xs(1)				                    
    IF f(1)=3 THEN :f(1)=7 :x(1)=x(1)-8 :ENDIF			
    IF f(1)=4 AND x(1)=0 THEN:
        PUT IMAGE background AT x(1),y(1)
		x(1)=216 :y(1)=RND(115)+35 			
        v=RND(2)+1        
    ENDIF    
END PROC  

PROCEDURE ffire
    IF fr=1 THEN:
        PUT BITMAP laser AT x(2)+24,y(2)     
        x(2)=x(2)+8
        IF x(2)>=216 THEN:
            PUT IMAGE background AT x(2)+24,y(2)
            x(2)=x(0):y(2)=y(0)
            fr=0
        ENDIF		       
    ELSE:
        x(2)=x(0):y(2)=y(0)	      
    ENDIF
END PROC

BEGIN GAMELOOP
    FOR z=1 TO v
        enemyShip[]
    NEXT

    IF JFIRE(0)=TRUE THEN fr=1    
    ffire[]

    movementShip[]
END GAMELOOP

Image

Image
Image
User avatar
ericomont
Posts: 29
Joined: Sun Oct 08, 2023 11:31 am

Re: Help making a basic game for CoCo 2

Post by ericomont »

Very nice!
Moves around like butter :D
Image

I haven´t used the ROLL either, chose to have the bitmaps hand positioned.
spotlessmind1975
Site Admin
Posts: 204
Joined: Fri Oct 06, 2023 8:25 pm

Re: Help making a basic game for CoCo 2

Post by spotlessmind1975 »

Hi Giovani_Gualdi!
Giovani_Gualdi wrote: Tue Mar 25, 2025 9:26 pm Here's another part of the space saga
A truly remarkable work, congratulations! :D
Post Reply