A simple miner program

Game development specific discussions.
BasicCoder2
Posts: 3525
Joined: Jan 01, 2009 7:03

A simple miner program

Postby BasicCoder2 » Mar 22, 2020 7:02

Here is another simple miner game code but this time using 64x64 tiles and a single sprite plus scrolling.
Use cursor keys to move left/right or climb up/down a ladder"
Hold down space bar at the same time as pressing an arrow key to work the drill"
Tap [b] key to build a ladder at current location of miner"
This version will load the png images using FBImage.bi
viewtopic.php?f=14&t=24105

Code: Select all

chdir exepath()
#include once "FBImage.bi"

' dodicat's regulate function
Function Regulate(Byval MyFps As Integer,Byref fps As Integer) As Integer
    Static As Double timervalue,lastsleeptime,t3,frames
    var t=Timer
    frames+=1
    If (t-t3)>=1 Then t3=t:fps=frames:frames=0
    Var sleeptime=lastsleeptime+((1/myfps)-T+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    lastsleeptime=sleeptime
    timervalue=T
    Return sleeptime
End Function

const TMAPW = 20   'size of tile array
const TMAPH = 15

const TILEW = 64   'size of tile
const TILEH = 64

const WINW = 640   'size of window over BMAP
const WINH = 480

const BMAPW = 1280  'size of bitmap of tile array
const BMAPH = 960

dim shared as integer WINX,WINY   'position of window over tiles display

screenres 640,480,32
color rgb(0,0,0),rgb(255,255,255):cls   'white paper, pen black

dim shared as any ptr minerSheet64
minerSheet64 = imagecreate(512,576)
'bload "minerSheet64.bmp",minerSheet64
minerSheet64 = LoadRGBAFile("miner-Sheet64.png")


dim shared as any ptr tileSheet
tileSheet = imagecreate(512,64)
'bload "tileSheet64.bmp",tileSheet
tileSheet = LoadRGBAFile("tile-Sheet64.png")

dim shared as any ptr background
background = imagecreate(BMAPW,BMAPH)
'create a background image
line background,(0,0)-(1279,191),rgb(100,100,255),bf
line background,(0,192)-(1279,959),rgb(200,100,0),bf

dim shared as any ptr ladder
ladder = imagecreate(TILEW,TILEH)
'bload "ladder64.bmp",ladder
ladder = LoadRGBAFile("ladder64.png")

dim shared as any ptr nugget
nugget = imagecreate(TILEW,TILEH)
'bload "nugget64.bmp",nugget
nugget = LoadRGBAFile("nugget64.png")

dim shared as any ptr DISPLAY
DISPLAY = imagecreate(1280,960)  'draw display


type SPRITE
    as integer x         'current pixel position
    as integer y
    as integer w         'width and height of image
    as integer h
    as integer dx        'change in pixel position per frame
    as integer dy
    as integer f         'image frame number
    as integer s         'image strip number
end type

dim shared as SPRITE miner   'create an sprite

dim shared as integer gotDrill
dim shared as integer goldTotal
dim shared as integer TX,TY      'tile to animate during drilling

miner.x = 100
miner.y = 100
miner.dx = 1
miner.dy = 1
miner.w  = 64
miner.h  = 64
miner.f  = 0
miner.s  = 5   'walk right with drill
dim shared as integer frameCounter


dim shared as integer TMAP(0 to TMAPW-1,0 to TMAPH-1)

for j as integer = 0 to 14
    for i as integer = 0 to 19
        read TMAP(i,j)
    next i
next j

dim shared as integer GMAP(0 to TMAPW-1,0 to TMAPH-1)  'GOLD TILE MAP
for i as integer = 0 to 20
    GMAP(int(Rnd(1)*20),int(rnd(1)*10)+3) = 1
next i

sub updateDisplay()
    dim as integer TILEX,TILEY
   
    line DISPLAY,(0,0)-(BMAPW-1,BMAPH-1),rgb(255,0,255),bf  'clear bitmap
    put DISPLAY,(0,0),background,trans
   
    for j as integer = 0 to 14
        for i as integer = 0 to 19
           
            put DISPLAY,(i*64,j*64),tileSheet,(TMAP(i,j)*64,0)-(TMAP(i,j)*64+63,63),trans
           
            'draw any overlay tiles
            if GMAP(i,j) = 2 then
                put DISPLAY,(i*TILEW,j*TILEH),ladder,trans
            end if
            if GMAP(i,j) = 1 then
                put DISPLAY,(i*TILEW,j*TILEH),nugget,trans
            end if
           
        next i
    next j
   
    'draw miner
    put DISPLAY,(miner.x,miner.y),minerSheet64,(miner.f*TILEW,miner.s*TILEH)-(miner.f*TILEW+63,miner.s*TILEH+63),trans
   
    'update frame
    frameCounter = frameCounter + 1
    if frameCounter > 8 then
        frameCounter = 0
        miner.f = miner.f + 1
        if miner.f = 4 then    'four frames
            miner.f = 0
        end if

        if TMAP(TX,TY) > 0 then
            TMAP(TX,TY)=TMAP(TX,TY)-1
        end if
       
    end if

end sub

sub update()
    updateDisplay()  'draw background, tiles and miner
    screenlock
    cls
    put (0,0),DISPLAY,(WINX,WINY)-(WINX+WINW-1,WINY+WINH-1),trans
    locate 2,1
    print " Use cursor keys to move left/right or climb up/down a ladder"
    print " Hold down space bar at same time to work the drill"
    print " Tap [b] key to build a ladder at current locations"
    print " Gold Total = ";goldTotal
    screenunlock
end sub

dim as integer TILEX,TILEY   'current tile array number occupied by character
Dim As Integer fps


do
       
    update()
   
    dim as integer onTile
    onTile = 0
   
    'test if miner.x,miner.y is in the center of a tile
    if miner.x = int(miner.x\TILEW)*TILEW and miner.y = int(miner.y\TILEH)*TILEH then
        onTile = 1  'yes on center
    end if
   
    if onTile = 1 then
   
        gotDrill = 0  'turn drill off
       
        TILEX = int(miner.x\TILEW)  'get tile coordinates of current tile
        TILEY = int(miner.y\TILEH)
       
        miner.dx = 0  'stop walking
        miner.dy = 0
        miner.s  = 4  'face player
       
        if multikey(&H39) then  'if SPACE BAR PRESS
            gotDrill = 1 'turn drill on
        end if
       
        if multikey(&H30) then   ' [b] key press
            GMAP(TILEX,TILEY)=2  'build ladder
        end if
   
        if multikey(&H4D) then
            if gotDrill = 1 then
                if TMAP(TILEX+1,TILEY)>0 then 'drill right
                    miner.dx = 2
                    miner.dy = 0
                    miner.s  = 5
                    TMAP(TILEX+1,TILEY)=3  'remove dirt
                    TX = TILEX+1 'tile to animate
                    TY = TILEY
                end if
            else
                if TMAP(TILEX+1,TILEY) = 0 then 'walk right
                    miner.dx = 2
                    miner.dy = 0
                    miner.s = 0
                end if
            end if
        end if
       
               
        if multikey(&H4B) then 'move left
            if gotDrill = 1 then
                if TMAP(TILEX-1,TILEY)>0 then 'drill left
                    miner.dx = -2
                    miner.dy = 0
                    miner.s  = 6
                    TMAP(TILEX-1,TILEY)=3
                    TY = TILEY    'tile to animate
                    TX = TILEX-1
                end if
            else
                if TMAP(TILEX-1,TILEY) = 0 then 'walk left
                    miner.dx = -2
                    miner.dy = 0
                    miner.s  =  1
                end if
            end if
        end if
       

        if multikey(&H48) then
            if gotDrill = 1 then
                if TMAP(TILEX,TILEY-1)>0 then  'drill up
                    miner.dy = -2
                    miner.dx = 0
                    miner.s  = 8
                    TMAP(TILEX,TILEY-1)=3
                    TX = TILEX  'tile to animate
                    TY = TILEY-1
                end if
            else
                if GMAP(TILEX,TILEY)= 2 and TMAP(TILEX,TILEY-1) <> 7 then  'up ladder
                    miner.dy = -2
                    miner.dx = 0
                    miner.s  = 2  'climb
                end if
            end if
        end if
       
       
        if multikey(&H50) then
            if gotDrill = 1 then
                if TMAP(TILEX,TILEY+1)>0 then  'drill down
                    miner.dy = 2
                    miner.dx = 0
                    miner.s  = 7
                    TMAP(TILEX,TILEY+1)=3
                    TX = TILEX
                    TY = TILEY + 1  'tile to animate
                end if
            else
                if GMAP(TILEX,TILEY+1) = 2 then 'down ladder
                    miner.dy = 2
                    miner.dx = 0
                    miner.s  = 2
                end if
            end if
        end if
       
        'gravity
        if TMAP(TILEX,TILEY+1)=0 and GMAP(TILEX,TILEY+1) <> 2 then
            miner.dy = 2
            miner.dx = 0  'no side movement
            miner.s  = 3
        end if
       
        'score any gold find
        if GMAP(TILEX,TILEY)= 1 then 'found gold
            goldTotal = goldTotal + 1
            GMAP(TILEX,TILEY)= 0  'remove gold
        end if
       
    end if

    'make move to next tile
    miner.x = miner.x + miner.dx
    miner.y = miner.y + miner.dy

    'check for out of boundary
    if miner.x < 0 then miner.x = 0
    if miner.x > TMAPW*TILEW-TILEW then
        miner.x = miner.x - miner.dx
    end if
    if miner.y < 0 then miner.y = 0
    if miner.y > TMAPH*TILEH-TILEH then
        miner.y = miner.y - miner.dy
    end if
   
    'compute window position
    WINX = miner.x - WINW\2
    if WINX < 0 then WINX = 0
    if WINX + WINW >= BMAPW then WINX = BMAPW-WINW
    WINY = miner.y - WINH\2
    if WINY < 0 then WINY = 0
    if WINY + WINH >= BMAPH then WINY = BMAPH-WINH
   
    Sleep regulate(60,fps),1
   
loop until multikey(&H01)

ImageDestroy minerSheet64
ImageDestroy tileSheet
ImageDestroy ladder
ImageDestroy nugget

'tile array data
data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
data 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7


Image
Image
Image
Image
Last edited by BasicCoder2 on Mar 25, 2020 20:32, edited 2 times in total.
BasicCoder2
Posts: 3525
Joined: Jan 01, 2009 7:03

Re: Another miner code - UPDATE

Postby BasicCoder2 » Mar 22, 2020 22:42

deleted
Last edited by BasicCoder2 on Mar 23, 2020 0:48, edited 1 time in total.
badidea
Posts: 2007
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Another miner code - UPDATE

Postby badidea » Mar 22, 2020 23:24

Amazing right, how quickly game code gets messy? All these different states and conditions to deal with.

BasicCoder2 wrote:Another option to converting the bmp images to png images is to use FBImage.bi and load them directly as shown below./
It requires FBImage.bi to be included.

I download the PNGs and ran "mogrify -verbose -format bmp *.png" to batch convert them form the command line. minerSheet and tileSheet had again a "-" in it after downloading.

BasicCoder2 wrote:I am not sure how important it is to use ImageDestroy?

On exit, freebasic should clean up everything (memory) nicely. But it this better to do it yourself in case the game gets bigger and e.g. you decide to load different images for a next level. Then things could get messy if you forget ImageDestroy.

I have mentioned before, you use sleep() to determine the walking and animation speed. But the sleep() time is not reliable.
BasicCoder2
Posts: 3525
Joined: Jan 01, 2009 7:03

Re: A simple miner program

Postby BasicCoder2 » Mar 23, 2020 0:53

Yes it can get messy dealing with states and conditions. I am thinking about how to manage it better.
Have used dodicat's regulator function for timing... is that any better? See first post.
I have been working on better images and ways of managing the animations.
badidea
Posts: 2007
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: A simple miner program

Postby badidea » Mar 23, 2020 12:13

BasicCoder2 wrote:Yes it can get messy dealing with states and conditions. I am thinking about how to manage it better.
Have used dodicat's regulator function for timing... is that any better? See first post.
I have been working on better images and ways of managing the animations.

Dodicat's regulator is simple solution which might work. I use a different system for timing thing. I'll try to post an example of this later.
BasicCoder2
Posts: 3525
Joined: Jan 01, 2009 7:03

Re: A simple miner program

Postby BasicCoder2 » Mar 23, 2020 19:57

badidea wrote:I use a different system for timing thing. I'll try to post an example of this later.

Ok. Always interested in how others go about it.
Just trying to keep the code simple. Usually I would just use the timer as shown below.
Again postimage.org changes the underscore to a minus sign which FB will not accept in a variable name.

Code: Select all

chdir exepath()
#include once "FBImage.bi"

screenres 1280,480,32
color rgb(0,0,0),rgb(255,255,255):cls

dim shared as any ptr miner_walk_right
miner_walk_right = imagecreate(512,64)
'bload "miner_walk_right",miner_walk_right
miner_walk_right = LoadRGBAFile("miner-walk-right.png")

dim as integer x,y,f

dim as double time1
time1 = timer

x = 0
y = 0
f = 0  'frame
do
    if timer - time1 > 0.2 then
        time1 = timer
        cls
        put (x,y),miner_walk_right,(f*64,0)-(f*64+63,63),trans
        line (0,64)-(1279,64),rgb(20,20,0)
        x = x + 4
        f = f + 1
        if f = 8 then f = 0
    end if
    sleep 2
loop until x = 1260 or multikey(&H01)

ImageDestroy miner_walk_right



Image
badidea
Posts: 2007
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: A simple miner program

Postby badidea » Mar 23, 2020 23:40

BasicCoder2 wrote:Just trying to keep the code simple. Usually I would just use the timer as shown below.
...

Yes, that is basically the idea, using a timer independent for animation and movement speed, independent of the loop time.
I use floating point for position, which complicates thing, but allows smaller movement steps, e.g. when including acceleration.

This re-write contains a lot of extra variables, which I normally put in a separate class/type. Then the main code gets cleaner again.
The miner walks a bit like Michael Jackson now, but this is less visible for a shorter frameDuration (e.g 0.1).

Code: Select all

chdir exepath() 'not needed here

screenres 1280, 480, 32
color rgb(0, 0, 0), rgb(255, 255, 255)
cls

dim as any ptr pMinerWalkRight
pMinerWalkRight = imagecreate(512, 64)
bload "miner-walk-right.bmp", pMinerWalkRight

dim as integer frame
dim as double tNow, tPrev, dt
dim as double nextFrameTime
dim as double frameDuration = 0.2
dim as single x, y
dim as single walkSpeed = 4 / frameDuration '20 pixels/s

x = 0 : y = 0
frame = 0
tNow = timer
nextFrameTime = tNow + frameDuration
do
   tPrev = tNow
   tNow = timer
   dt = tNow - tPrev
   'update miner frame
   if tNow > nextFrameTime then
      nextFrameTime = tNow + frameDuration
      frame += 1
      if frame = 8 then frame = 0
   end if
   'update position
   x += walkSpeed * dt
   'drawing part
   screenlock
   cls
   put(cint(x), cint(y)), pMinerWalkRight, (frame * 64, 0)-step(63, 63), trans
   line (0, 64)-(1279, 64), rgb(20, 20, 0) 'floor
   screenunlock
   'take a quick nap
   sleep 1
loop until x = 1260 or multikey(&H01)

ImageDestroy pMinerWalkRight

In my tetris game, I run multiple position updates (for collision detection) for 1 graphics update.
If dt > 10 ms then do x += walkSpeed * dt multiple times in smaller steps. Bit a bit pointless here.
And if the miner can only move from 1 grid location to the next then things can be kept more simple.
badidea
Posts: 2007
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: A simple miner program

Postby badidea » Mar 24, 2020 23:05

I would probably write it like this with classes/UDT:

Code: Select all

type miner_type
   'image/frame info
   private:
   dim as any ptr pMinerWalkRight
   dim as integer activeFrame
   dim as integer frameWidth, frameHeight, numFrames
   dim as double nextFrameTime, frameDuration
   public:
   dim as double x, y, walkSpeed
   declare constructor()
   declare destructor()
   declare sub loadFrames(fileName as string)
   declare sub updateFrame()
   declare sub updatePos(dt as double)
   declare sub draw_()
end type

constructor miner_type()
   loadFrames("miner-walk-right.bmp")
   activeFrame = 0
   frameDuration = 0.1
   nextFrameTime = timer + frameDuration
   x = 0 : y = 0
   walkSpeed = 5.0 / frameDuration '50 pixels/s
end constructor

destructor miner_type()
   if pMinerWalkRight <> 0 then
      ImageDestroy(pMinerWalkRight)
      pMinerWalkRight = 0
   end if
end destructor

sub miner_type.loadFrames(fileName as string)
   frameWidth = 64
   frameHeight = 64
   numFrames = 8
   pMinerWalkRight = imagecreate(frameWidth * numFrames, frameHeight)
   bload(fileName, pMinerWalkRight)
end sub

sub miner_type.updateFrame()
   if timer > nextFrameTime then
      nextFrameTime = timer + frameDuration
      activeFrame += 1
      if activeFrame = 8 then activeFrame = 0
   end if
end sub

sub miner_type.updatePos(dt as double)
   x += walkSpeed * dt
end sub

sub miner_type.draw_()
   put(cint(x), cint(y)), pMinerWalkRight, (activeFrame * frameWidth, 0)-_
      step(frameWidth - 1, frameHeight - 1), trans
end sub

'-------------------------------------------------------------------------------

type loop_timer
   private:
   dim as double tPrev, tNow, tStep
   public:
   declare constructor()
   declare sub update()
   declare function dt() as double
end type

constructor loop_timer()
   update() 'initialize values
end constructor

sub loop_timer.update()
   tPrev = tNow
   tNow = timer
   tStep = tNow - tPrev
end sub

function loop_timer.dt() as double
   return tStep
end function

'-------------------------------------------------------------------------------

const SCRN_W = 1280, SCRN_H = 480

sub drawWorld()
   line (0, 64)-(SCRN_W - 1, 64), rgb(20, 20, 0) 'floor
end sub

'-------------------------------------------------------------------------------

screenres(SCRN_W, SCRN_H, 32)
color rgb(0, 0, 0), rgb(255, 255, 255)

dim as miner_type miner 'load the image via constructor
dim as loop_timer loopTimer 'initialize via constructor

do
   loopTimer.update()
   miner.updateFrame()
   miner.updatePos(loopTimer.dt())

   screenlock
   cls
   miner.draw_()
   drawWorld()
   screenunlock

   sleep 1
loop until miner.x = 1260 or multikey(&H01) 'escape key

'no ImageDestroy needed, via miner.destructor() automatically

This code is 3 times as long however. The main loop, on the other hand, is cleaner.

The biggest problem for me is often: How do the classes communicate. For example, the miner needs to interact with the world. In this case, the world is a single line. How do I tell the miner where this line (floor) is, so it does not drop into oblivion.
BasicCoder2
Posts: 3525
Joined: Jan 01, 2009 7:03

Re: A simple miner program

Postby BasicCoder2 » Mar 25, 2020 4:04

badidea wrote:The miner walks a bit like Michael Jackson now, ...


Of course you are concentrating on the game code and better animations can always be added later should you so desire.
Although i have used floating point positioning in other programs in this case I am locking the frames to exact pixel positions. This means there is no sliding of the character because the frames are slower or faster than the change in pixel position.

On large more detailed images the more frames the smoother the movements. I see eight frames per animations as a good compromise for 64x64 tiles. With 48x48 tiles you could use 6 frames per animation. In my case I like to cycle the whole animation strip completely one or more times. In the example below one animation strip will take the character moving at 8 pixels per frame from one 64x64 tile to another.

The example code below uses this animation strip I drew this morning loosely based on the character you are using.
Notice how the character steps exactly on each block.

Image

In this example the character moves one FRAME when you tap the space bar.

Code: Select all

chdir exepath()
#include once "FBImage.bi"

screenres 1280,480,32
color rgb(0,0,0),rgb(255,255,255):cls

dim shared as any ptr walkRight64
walkRight64 = imagecreate(512,64)
'bload "badideaWalker4.bmp",walkRight64
walkRight64 = LoadRGBAFile("walk-Right64.png")

dim as integer x,y,f

dim as double time1
time1 = timer

x = 0
y = 0
f = 0  'frame
do
   ' if timer - time1 > 0.8 then
    '    time1 = timer
        screenlock
        cls
        'draw blocks
        for k as integer = 0 to 79 step 2
            line (k*16+20,63)-(k*16+36,70),rgb(255,0,0),bf  'walking blocks
        next k
        for k as integer = 0 to 1280
            line (k*64,0)-(k*64+63,63),rgb(0,0,255),b        'tiles
        next k

        put (x,y),walkRight64,(f*64,0)-(f*64+63,63),trans
        locate 12,1
        print " frame =";f
        print
        print " HIT SPACE BAR TO ADVANCE FRAME"
        print
        print " HIT ESC TO EXIT PROGRAM"
        screenunlock
        x = x + 8
        f = f + 1
        if f = 8 then f = 0
    'end if
    sleep
loop until x = 1260 or multikey(&H01)

ImageDestroy walkRight64



And it this example the character moves one TILE when you tap the space bar.

Code: Select all

chdir exepath()
#include once "FBImage.bi"

screenres 1280,480,32
color rgb(0,0,0),rgb(255,255,255):cls

dim shared as any ptr walkRight64
walkRight64 = imagecreate(512,64)
'bload "badideaWalker4.bmp",walkRight64
walkRight64 = LoadRGBAFile("walk-Right64.png")

dim as integer x,y,f,dx

dim as double time1
time1 = timer

x = 0
y = 0
f = 0  'frame
dx = 8 'move image right 8 pixels per frame

do
   
    if timer - time1 > 0.1 then
        time1 = timer
        screenlock
        cls
        'draw blocks
        for k as integer = 0 to 79 step 2
            line (k*16+20,63)-(k*16+36,70),rgb(255,0,0),bf  'walking blocks
        next k
        for k as integer = 0 to 1280
            line (k*64,0)-(k*64+63,63),rgb(0,0,255),b       'draw tiles
        next k

        put (x,y),walkRight64,(f*64,0)-(f*64+63,63),trans
        locate 12,1
        print " frame =";f
        print
        print " HIT SPACE BAR TO MOVE TO NEXT TILE"
        print
        print " HIT ESC TO EXIT PROGRAM"
        print
        print x-(int(x\64)*64)
        screenunlock
       
        x = x + dx
        f = f + 1
        if f = 8 then f = 0
 
        if x-(int(x\64)*64)=0 then  'test if on tile
            dx = 0
            f = 0
        end if
       
    end if

    if multikey(&H39) then dx = 8  'if press space bar go to next tile
   
    sleep 2
loop until x = 1260 or multikey(&H01)

ImageDestroy walkRight64
Last edited by BasicCoder2 on Mar 25, 2020 23:32, edited 1 time in total.
D.J.Peters
Posts: 8023
Joined: May 28, 2005 3:28
Contact:

Re: A simple miner program

Postby D.J.Peters » Mar 25, 2020 4:57

Here are how to mirror a right walk to left walk and create one image strip with right and left walk circles.
(in case if MultiPut V2.0 are too much)
Image
NOTE: testfile "miner-walk-right.png" must be in the same folder !
Of course you can mirror any image vertical or horizontal but for this small test the filename are hard coded !

Joshy

Code: Select all

#include once "FBImage.bi"
' mirror image or screen vertical or horizontal
sub Mirror(byval img as any ptr=0, byval iHorizontal as integer=1)
  static as integer oWidth=0,oHeight=0,oHorizontal=0
  static as any ptr imgA=0,imgB=0
  dim as integer iWidth=any,iHeight=any
  dim as integer xSize=any,ySize=any,xStart=any,yStart,xStep=any,yStep=any
  dim as integer x1=any,x2=any,y1=any,y2=any,iStart=any,iEnd=any
  if img=0 then ' screen
    if ScreenPtr()=0 then exit sub
    ScreenInfo(iWidth,iHeight)
  else ' image
    if ImageInfo(img,iWidth,iHeight) then exit sub
  end if
  if iHorizontal then iHorizontal=1
  ' realloc images only if the resolution or the mirror axis are changed !
  if iWidth<>oWidth orelse iHeight<>oHeight orelse oHorizontal<>iHorizontal then
    oWidth = iWidth : oHeight = iHeight : oHorizontal = iHorizontal
    if iHorizontal then
      xSize=iWidth : ySize=1
    else
      xSize=1: ySize=iHeight
    end if
    if ImgA then ImageDestroy ImgA:ImgA=0
    if ImgB then ImageDestroy ImgB:ImgB=0
    imgA=imageCreate(xSize,ySize)
    imgB=imageCreate(xSize,ySize)
  end if
  ' now the magic :lol:
  xSize-=1 : ySize-=1
  if iHorizontal then
    x1=0:x2=0:y1=0:y2=iHeight-1 : xStep=0:yStep=1 : iStart=0:iEnd=iHeight-1
  else
    x1=0:x2=iWidth-1:y1=0:y2=0  : xStep=1:yStep=0 : iStart=0:iEnd=iWidth-1
  end if
  while iStart<=iEnd
    Get img,(x1,y1)-step(xSize,ySize), imgA
    Get img,(x2,y2)-step(xSize,ySize), imgB
    Put img,(x1,y1),imgB,pset
    Put img,(x2,y2),imgA,pset
    x1+=xStep : x2-=xStep
    y1+=yStep : y2-=yStep
    iStart+=1 : iEnd-=1
  wend

end sub

const MinerFile = "miner-walk-right.png"

function CreateMinerWalk() as any ptr
  dim as any ptr tmp(1)
  tmp(0) = LoadRGBAFile(MinerFile)
  if tmp(0)=0 then
    screen 0
    print "error: while loading '" & Minerfile & "' !"
    print *GetLastResult()
    beep : sleep: end 1
  end if
  tmp(1) = LoadRGBAFile(MinerFile)
  Mirror(tmp(1),false)
  var iWidth=0,iHeight=0
  ImageInfo tmp(0),iWidth,iHeight
  var ImageStrip = ImageCreate(iWidth,iHeight*2)
  for i as integer=0 to 1
    put ImageStrip,(0,i*iHeight),tmp(i),PSET
    imagedestroy tmp(i)
  next 
  return ImageStrip
end function

chdir exepath()
screenres 640,480,32
var miner = CreateMinerWalk()
put (0,0),miner,TRANS
#include once "FBImage.bi"
' mirror image or screen vertical or horizontal
sub Mirror(byval img as any ptr=0, byval iHorizontal as integer=1)
  static as integer oWidth=0,oHeight=0,oHorizontal=0
  static as any ptr imgA=0,imgB=0
  dim as integer iWidth=any,iHeight=any
  dim as integer xSize=any,ySize=any,xStart=any,yStart,xStep=any,yStep=any
  dim as integer x1=any,x2=any,y1=any,y2=any,iStart=any,iEnd=any
  if img=0 then ' screen
    if ScreenPtr()=0 then exit sub
    ScreenInfo(iWidth,iHeight)
  else ' image
    if ImageInfo(img,iWidth,iHeight) then exit sub
  end if
  if iHorizontal then iHorizontal=1
  ' realloc images only if the resolution or the mirror axis are changed !
  if iWidth<>oWidth orelse iHeight<>oHeight orelse oHorizontal<>iHorizontal then
    oWidth = iWidth : oHeight = iHeight : oHorizontal = iHorizontal
    if iHorizontal then
      xSize=iWidth : ySize=1
    else
      xSize=1: ySize=iHeight
    end if
    if ImgA then ImageDestroy ImgA:ImgA=0
    if ImgB then ImageDestroy ImgB:ImgB=0
    imgA=imageCreate(xSize,ySize)
    imgB=imageCreate(xSize,ySize)
  end if
  ' now the magic :lol:
  xSize-=1 : ySize-=1
  if iHorizontal then
    x1=0:x2=0:y1=0:y2=iHeight-1 : xStep=0:yStep=1 : iStart=0:iEnd=iHeight-1
  else
    x1=0:x2=iWidth-1:y1=0:y2=0  : xStep=1:yStep=0 : iStart=0:iEnd=iWidth-1
  end if
  while iStart<=iEnd
    Get img,(x1,y1)-step(xSize,ySize), imgA
    Get img,(x2,y2)-step(xSize,ySize), imgB
    Put img,(x1,y1),imgB,pset
    Put img,(x2,y2),imgA,pset
    x1+=xStep : x2-=xStep
    y1+=yStep : y2-=yStep
    iStart+=1 : iEnd-=1
  wend

end sub

const MinerFile = "miner-walk-right.png"

function CreateMinerWalk() as any ptr
  dim as any ptr tmp(1)
  tmp(0) = LoadRGBAFile(MinerFile)
  if tmp(0)=0 then
    screen 0
    print "error: while loading '" & Minerfile & "' !"
    print *GetLastResult()
    beep : sleep: end 1
  end if
  tmp(1) = LoadRGBAFile(MinerFile)
  Mirror(tmp(1),false)
  var iWidth=0,iHeight=0
  ImageInfo tmp(0),iWidth,iHeight
  var ImageStrip = ImageCreate(iWidth,iHeight*2)
  for i as integer=0 to 1
    put ImageStrip,(0,i*iHeight),tmp(i),PSET
    imagedestroy tmp(i)
  next 
  return ImageStrip
end function

chdir exepath()
screenres 512,128,32
var miner = CreateMinerWalk()
put (0,0),miner,TRANS
' SavePNGFile(miner,"miner_right_left.png")
sleep
BasicCoder2
Posts: 3525
Joined: Jan 01, 2009 7:03

Re: A simple miner program

Postby BasicCoder2 » Mar 25, 2020 10:49

I used fbImage in the posted examples because Postimage.org converts my .bmp images to .png images. I usually only use bitmaps.
This is how I converted the right walking sprites to left walking sprites on this particular sprite sheet.

Code: Select all

screenres 512,128,32  'screen size of desired resulting sheetmap
bload "walkRight.bmp"  '512 x 64 sheetmap with right walking sprites
    for j as integer = 0 to 63 'height of images
        for i as integer = 0 to 511  'width of bitmap sheet
            pset ((511-i),j+64),point(i,j)  'create a left walking strip below the right walking strip
        next i
    next j
bsave "walkRightLeft.bmp",0  'save the new version
sleep
BasicCoder2
Posts: 3525
Joined: Jan 01, 2009 7:03

miner demo program [classes]

Postby BasicCoder2 » Mar 29, 2020 19:17

badidea wrote:The biggest problem for me is often: How do the classes communicate. For example, the miner needs to interact with the world. In this case, the world is a single line. How do I tell the miner where this line (floor) is, so it does not drop into oblivion.

@badidea
It is not an issue for me as I don't use classes. Many years ago I spent some time trying to get my head around c++ classes but they just seemed to add enormous amounts of extra paper work to the program without making it any easier for me to understand how they actually worked. However I did find using c++ classes easy and they did make my main code simpler. Perhaps moving from c++ to FreeBASIC over 11 years ago when it had no oop support has addled my brain :)

Being home bound due to the Corona virus restrictions has given me some extra spare time to rewrite the miner game demo and I even used the same graphics you are using as well as trying to duplicate some of the behaviours. The miner now has a state variable with an associated animation which makes it easier to follow and manage the code.

With the images you are using I noticed all these annoying light gray pixels around the outlines which I removed. However thinking about it maybe they are transparent pixels to blend into the background? I never bother with the transparency thing and PAINT loses the transparency when the images are saved.
badidea
Posts: 2007
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: miner demo program [classes]

Postby badidea » Mar 29, 2020 20:02

BasicCoder2 wrote:Being home bound due to the Corona virus restrictions has given me some extra spare time to rewrite the miner game demo and I even used the same graphics you are using as well as trying to duplicate some of the behaviours.

I thought that I would have more time now due to this virus, but still busy with all kinds of things.

BasicCoder2 wrote:With the images you are using I noticed all these annoying light gray pixels around the outlines which I removed. However thinking about it maybe they are transparent pixels to blend into the background? I never bother with the transparency thing and PAINT loses the transparency when the images are saved.

I only use 'alpha blending' everywhere in the game, no transparency with the pink background. With the "fb.GFX_ALPHA_PRIMITIVES" in screenres():
"GFX_ALPHA_PRIMITIVES: Tells the graphics library to enable alpha channel support for all drawing primitives. This means the alpha specified in a color value (via either the RGBA macro or direct color in the form &hAARRGGBB) will always be used by all primitives."
BasicCoder2
Posts: 3525
Joined: Jan 01, 2009 7:03

Re: A simple miner program

Postby BasicCoder2 » Apr 05, 2020 20:25

@badidea

I have had time to spend on reworking game "engines" and try out some game ideas.

I have played with the same graphics you are/were using but the code has to adapt to the images not the other way around. For example the cracking of a tile involves an overlay not a cracked image. I overlayed the gems on the tile whereas in the images you are using there are tiles with gems as part of the image and the cracking is overlayed.

With a walking animation I would have a strip of images within a larger image (usually called a sheet) but I see with the images you are using each frame is independent.
act_walk_1 act_walk_2 act_walk_3 act_walk_4

I found using alpha works with the images. Using trans shows strange black areas. Filling an image with magenta results in strange light grey pixel noise.

Code: Select all

screenres 640,480,32
color rgb(0,0,0),rgb(100,100,255):cls
chdir exepath() ' !!! for image loading be sure it's the right folder
dim shared as any ptr images(1 to 4)
for i as integer = 1 to 4
    images(i) = imagecreate(64,64)
next i
bload "images/actor/act_walk_1.bmp",images(1)
bload "images/actor/act_walk_2.bmp",images(2)
bload "images/actor/act_walk_3.bmp",images(3)
bload "images/actor/act_walk_4.bmp",images(4)
dim as integer x,y,frame
frame = 1
do
    screenlock
    cls
    put (x,y),images(frame),alpha
    screenunlock
   
    frame = frame + 1
    if frame = 5 then frame = 1
    x = x + 4
    if x > 640 then x = 0
    sleep
loop until multikey(&H01)
badidea
Posts: 2007
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: A simple miner program

Postby badidea » Apr 05, 2020 21:20

Quiet day / weekend here on the forum. Maybe everyone is in some sort of corona-depression?

BasicCoder2 wrote:With a walking animation I would have a strip of images within a larger image (usually called a sheet) but I see with the images you are using each frame is independent.

Using image sheets makes the images load faster from disk. For today's SSD not so important however.

BasicCoder2 wrote:I found using alpha works with the images. Using trans shows strange black areas. Filling an image with magenta results in strange light grey pixel noise.

Yes, when a pixel if fully transparent, the color is not important, I guess.

I was looking at my own game again today (after a short break), but I don't like how I did certain thing. So I am at the point of breaking the game and fixing it without making actual progress. A bit annoying.

Something else, in the post that you deleted (also a bit annoying), you wrote about the goal to collect as many diamonds in a certain time. I think that that is not a very exciting goal. The image set also contains artefacts (bones, ring, other weird stuff). Maybe you can out 1 artefact of each in the map with the goal to collect those, but with time running out. And by collecting diamonds, you can buy extra time.

Return to “Game Dev”

Who is online

Users browsing this forum: No registered users and 6 guests