Isopaint

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
sean_vn
Posts: 283
Joined: Aug 06, 2012 8:26

Isopaint

Post by sean_vn »

I have been experimenting with some of things you would need for an isometric game. I'm not sure if I got the paint order correct enough to be useful and there are some scaling issues that need to be fixed. Anyway...

Code: Select all

#include "crt/stdlib.bi"
#include "crt/string.bi"
#include "fbgfx.bi"
using FB
#define ScreenW 512
#define ScreenH 512
#define ScreenB ScreenH-1
#define ScreenM (ScreenW/2)
#define scan(x,n) for x as ulongint=0 to (n)
#define toIso(u,v,x,y) u=ScreenM+(x)-(y):v=ScreenB-(y)-(x)
#define mleft 1
#define mright -1
#define mtop 2
#define mbottom -2
#define mup 3
#define mdown -3 
#define nSprites 16

type sprite
	x as long
	y as long
	z as long
	dx as long
	dy as long
	dz as long
	movable as boolean
end type

dim shared as sprite mysprites(nSprites-1),copysprites(nSprites-1)
dim shared as sprite ptr draworder(nSprites-1)
dim shared as boolean spritedone(nSprites-1)

function cmpZ(u as sprite ptr ptr,v as sprite ptr ptr) as integer
	var z1=(*u)->z
	var z2=(*v)->z
	if z1=z2 then return 0
	return iif(z1<z2,1,-1)
end function

function cmpX(u as sprite ptr ptr,v as sprite ptr ptr) as integer
    if (*v)->x>(*u)->x then return 1
	return -1
end function

function cmpY(u as sprite ptr ptr,v as sprite ptr ptr) as integer
    if (*v)->y>(*u)->y then return 1
	return -1
end function

function intersect(sprite1 as ulong,sprite2 as ulong) as boolean
    with copysprites(sprite1)
       var x1=.x,dx1=.dx,y1=.y,dy1=.dy,z1=.z,dz1=.dz
    with copysprites(sprite2)
       var x2=.x,dx2=.dx,y2=.y,dy2=.dy,z2=.z,dz2=.dz
	if x2+dx2<x1 then return false
	if x2>x1+dx1 then return false
	if y2+dy2<y1 then return false
	if y2>y1+dy1 then return false
	if z2+dz2<z1 then return false
	if z2>z1+dz1 then return false
	return true
	end with
	end with
end function
	
function moveit(sprite1 as ulong, direction as long) as boolean
	with copysprites(sprite1)
	if .movable=false then return false
	select case direction
	case mleft 
		.x-=1
	case mright
		.x+=1
	case mtop
		.y+=1
	case mbottom
		.y-=1
	case mup
		.z+=1
	case mdown
		if .z = 0 then return false
		.z-=1
    end select
    end with
    spritedone(sprite1)=true
    scan(i,ubound(copysprites))
		if not spritedone(i) then
			if intersect(sprite1,i) then
				if not moveit(i,direction) then
					return false
				end if
			end if
		end if
	next
	return true
end function

sub move(sprite1 as ulong,direction as long)
    scan(i,ubound(spritedone)):spritedone(i)=false:next
	memcpy(@copysprites(0),@mysprites(0),sizeof(sprite)*nSprites)
	if moveit(sprite1,direction) then
		memcpy(@mysprites(0),@copysprites(0),sizeof(sprite)*nSprites)
	end if
end sub
		

''''''
screenres ScreenW,ScreenH,32
dim as long u1,v1,u2,v2

dim as any ptr isoTile
isoTile = imagecreate(31,46,0)
scan(i,15)
	circle isoTile,(15,i+15),15,rgb(200,255,200),,,,F
next
circle isoTile,(15,15),15,rgb(0,0,0) 

randomize()
scan(i,ubound(mysprites))
	draworder(i)=@mysprites(i)
	mysprites(i).x=i*18
	mysprites(i).y=i*18
	mysprites(i).dx=16
	mysprites(i).dy=16
	mysprites(i).dz=32
	mysprites(i).movable=true
next

scan(i,ubound(mysprites))
	swap mysprites(i).x,mysprites(int(ubound(mysprites)*rnd())).x
	swap mysprites(i).y,mysprites(int(ubound(mysprites)*rnd())).y
	mysprites(i).z=rnd()*50
next

Do
    ' Check arrow keys and update the (x, y) position accordingly
    If MultiKey(SC_LEFT ) then move(0,mleft)
    If MultiKey(SC_RIGHT) then move(0,mright)
    If MultiKey(SC_UP   ) then move(0,mtop)
    If MultiKey(SC_DOWN ) then move(0,mbottom)
    If MultiKey(SC_SPACE ) then move(0,mup):move(0,mup):move(0,mup):end if
    scan(i,ubound(mysprites))
		if mysprites(i).z>0 then move(i,mdown)
	next
    qsort(@draworder(0),ubound(draworder)+1,sizeof(sprite ptr),cptr(any ptr,@cmpZ))
	qsort(@draworder(0),ubound(draworder)+1,sizeof(sprite ptr),cptr(any ptr,@cmpX))
    qsort(@draworder(0),ubound(draworder)+1,sizeof(sprite ptr),cptr(any ptr,@cmpY))
    ScreenLock
        Cls
		scan(i,16)
			toIso(u1,v1,i*16,0)
			toIso(u2,v2,i*16,256)
			line (u1,v1)-(u2,v2)
		next
		scan(i,16)
			toIso(u1,v1,0,i*16)
			toIso(u2,v2,256,i*16)
			line (u1,v1)-(u2,v2)
		next
		scan(i,ubound(draworder))
			toIso(u1,v1,draworder(i)->x,draworder(i)->y)
			put (u1,v1-draworder(i)->z),isoTile,Alpha
		next
    ScreenUnlock
    sleep 15
Loop Until MultiKey(SC_ESCAPE)

counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Isopaint

Post by counting_pine »

Unfortunately, it segfaulted for me on Win32..
If I wrap the cmpX/Y/Z functions in an 'extern "c"' block, or make them all cdecl, it seems to work. I guess it only worked when the default calling convention was cdecl-compatible.
Anyway, having got it running, it looks pretty cool. I like the way the pieces interact.
sean_vn
Posts: 283
Joined: Aug 06, 2012 8:26

Re: Isopaint

Post by sean_vn »

There is only one calling convention with Linux AMD 64, I didn't stop to think about other systems. Cdecl is necessary for anything else.
I like the reduction in typing I get using #define scan(x,n) for x as ulongint=0 to (n)
I would guess if you used a few different sprites you would see some problem in the paint order. I just wanted to get a general idea about how to do an isometric game. I'll see if I can figure out how to do one of those old road racing games too.
BasicCoder2
Posts: 3917
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Isopaint

Post by BasicCoder2 »

The source code compiles but it fails to run when the qsort is called.
The actual display is not really isometric. It is a top down view of a grid rotate by 45 degrees.
You might get some ideas from other such tools,
http://hative.com/isometric-drawing-tools/

.
sean_vn
Posts: 283
Joined: Aug 06, 2012 8:26

Re: Isopaint

Post by sean_vn »

Yeh, it looked a bit off for isometric. I just very quickly copied some idea on the internet. I would say you just need to adjust the toIso macro. I'd be more concerned with the correctness of the paint order. I had done it in a different way but that caused some flickering effect that I didn't want to spend time tracking down.
For windows (not notPetya'ed?) maybe adding cdecl would help:
function cmpZ cdecl (u as sprite ptr ptr,v as sprite ptr ptr) as integer
etc.
I think the more modern way to do isometric is in simplified 3d. Just adjusting the camera to the correct angles. That way the paint order is automatically taken care of for you. You could write it in html 5 or processing I think.
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

Re: Isopaint

Post by leopardpm »

sean_vn wrote:I think the more modern way to do isometric is in simplified 3d. Just adjusting the camera to the correct angles. That way the paint order is automatically taken care of for you.....
That there is cheatin' in ma book!
BasicCoder2
Posts: 3917
Joined: Jan 01, 2009 7:03
Location: Australia

Re: Isopaint

Post by BasicCoder2 »

.
Last edited by BasicCoder2 on Jul 10, 2017 6:43, edited 1 time in total.
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Isopaint

Post by MrSwiss »

BasicCoder2 wrote:We are always "cheating" unless we write everything in raw assembler including all our own routines.
Sorry, even that isn't true, because:
  • 1) the CPU isn't designed by you (the micro-code it contains)
    2) the Assembler you are using, is OPC (other peoples code)
    3) the BIOS contains also OPC
You should slowly realize, that nobody can do it, all alone. Teamwork is the name of the Game.

I've by now, read that nonsense, written by you, enough times. Please stop repeating yourself,
every time you're frustrated, whatever the reason may be, it is getting very boring.
sean_vn
Posts: 283
Joined: Aug 06, 2012 8:26

Re: Isopaint

Post by sean_vn »

A storm in a teacup? Did someone drop some buttered bread on the floor? What happened? I don't know.
Post Reply