Invader Maker (Source Included)

BlitzMax Forums/BlitzMax Programming/Invader Maker (Source Included)

dw817(Posted 2015) [#1]


Random pixels making images is not something new to me. I remember writing a strange program on the Commodore Amiga years ago that created a fairly large picture of either a scary devil or a king with a crown, and the king always looked like a cat.

This occurred almost every random run, and it was generated entirely with random pixels.

Today I think how unusual it is that when you control the behavior of random variables, you can get some very unique results.

While you can indeed create 'creatures' simply shooting random pixels into a 4x8 field, mirroring it, and displaying it. This program goes a little further than that.

It ensures all pixels are connected and that all edges of the sprite field are touched. The results, a more 'believable' invader I believe. What do you think ? Run it until you find one that looks familiar from a recent shoot-em-up.






col(Posted 2016) [#2]
Just saw this post and while the code itself is questionable, the end result of this is actually pretty cool.


Brucey(Posted 2016) [#3]
BlitzMax lets you use variable names of more than 1 character...


dw817(Posted 2016) [#4]
Questionable ? Runs just fine here. Glad you like it. :) I'll update it slightly ... Ok, now you can just hit a key and it'll redo 'em. If you hit ESC it will exit.

Brucey, I know that. I do that for arrays and special cases, but not for simple variables. I suppose you would hate this which is what I have in the beginning of my main engine:
Local a,b,c,d,e,f,g,h,i,j,kk,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
Local aa$,bb$,cc$,dd$,ee$,ff$,gg$,hh$,ii$,jj$,ll$,mm$
Local nn$,oo$,pp$,qq$,rr$,ss$,tt$,uu$,vv$,ww$,xx$,yy$,zzz$
Why are are K and zz$ different ?

k$ is from early coding, to me it always represented a key hit so I try to use it only and exclusively for that. And you can see it's not in this local list but a global list above it.

zzz$ is used as I have a function zz() which is where I go when ready to exit the program - it's gotta save all the environmental variables and position first.

And (and I think this is a shortcoming of BlitzMAX), you cannot have 'a' and 'a$' No, you must have 'a' and 'aa$' rather not nice I think. Other languages allow it.


col(Posted 2016) [#5]
I'm curious,
Maybe I've misunderstood, but what language(s) allow the same variable name twice? I personally dislike that as when reading the code, unless you wrote it, then you'll need to know the 'type' of the variable to accurate read and decipher bugs. How do you know which 'version' of the variable is being updated by looking at a section of code? Especially if the language allows automatic 'numeric to string' and 'string to numeric' conversion.

Saying that... some newer languages are making use of 'type inference', which means the type of the variable is determined by its initial value, ie A = "test" will mean A becomes a string type, and A = 10 means A will be of an integer type. But they still won't allow the same variable name to be defined twice at the same time.


Brucey(Posted 2016) [#6]
You go on about how posting source is good for people to understand how things are done, yet you fill your code with pretty-much useless variable naming conventions.
Giving a beginner code like this:
           If l=0 Then c1=1 ' tricky, ensure that critter
            If l=3 Then c2=1 ' touches all 4-sides, no 6x8 or
            If k=0 Then c3=1 ' 8x7 sprite, always 8x8
            If k=7 Then c4=1
 

is meant to help them how? c1 represents what? and c3?
It appears you need to study the code in-depth just to work out what you are doing with your variables. It turns out that cx represent a side of a sprite?

you cannot have 'a' and 'a$'

That's because a and a$ are the same variable. You don't need to suffix your variable names with its type. It looks messy and old-fashioned.
If you have trouble remembering what type your variable is, then you may have a variable naming issue in your code - see my first point.

@ questionable
This seems rather wasteful :
Until c1+c2+c3+c4=4

You'd be better to use bit flags instead, I'd imagine.
Until sides = ALL_SIDES

where ALL_SIDES would have a value of $F.
and your sides calculation could be done along the lines of
           If l=0 Then sides :| LEFT_SIDE ' tricky, ensure that critter
            If l=3 Then sides :| RIGHT_SIDE ' touches all 4-sides, no 6x8 or
            If k=0 Then sides :| TOP_SIDE ' 8x7 sprite, always 8x8
            If k=7 Then sides  :| BOTTOM_SIDE

where side consts are defined along the lines of
Const LEFT_SIDE:Int = $1
Const RIGHT_SIDE:Int = $2
Const TOP_SIDE:Int = $4
Const BOTTOM_SIDE:Int = $8



dw817(Posted 2016) [#7]
Brucey, I'll be completely honest. This code:
   If l=0 Then sides :| LEFT_SIDE ' tricky, ensure that critter
            If l=3 Then sides :| RIGHT_SIDE ' touches all 4-sides, no 6x8 or
            If k=0 Then sides :| TOP_SIDE ' 8x7 sprite, always 8x8
            If k=7 Then sides  :| BOTTOM_SIDE
I've never seen code like that before and I don't even know how it works.

What is :| (the expression my face is showing right now). And sides, if it is not an array, what is it, where is the indices ?

As for the "l" (el). Yeah, I know, I need to get out of using that as a variable. I've been doing that for new code, but I wrote this one a few days earlier. Can touch it up easily to use variable "n" if you like.

Code updated. 01-09-16 7:07pm

Col, there are many programming languages that allow a and a$ to be separate.

More recent, B4GL, and going back you have, F-Basic Delphi Noetic, GFA-Basic, Q-Basic, GWBasic, Applesoft Basic, Integer Basic, T.R.S. 80 Basic, Sinclair 1000.

Shoot, even game programming legend David H. Ahl saw the value of strings and variables and would mix and match a and a$ all the time.

I mean, the variable IS defined. '$' represents a string. I'm not happy that in Monkey-X once I define it I can never type it again, I.E.:
Function fnc$(a$,b)
  Return a[b-1..b]
End
Notice how I cannot use a$ for return ! No, once I define a string for a function, global, or local, then the variable $ is forbidden and I have to remember what is what. That's really weird to me.


col(Posted 2016) [#8]
It's good to understand that we all come from different backgrounds with different understandings of how things work. Most languages that are worth their salt pretty much all do the exact same thing but will use a syntax that suits the language designer.

I'll never understand the logic of allowing 2 variables of different types with the same name to be used at the same time, that school of thought is way too 'old school' for me :D

The next set of paragraphs are going to be me brainstorming and typing at the same time so bear with me and hopefully I could help clear the fog for yourself and maybe even help others too, you may also know a lot of what I'm about to say but here goes...

Anyway, my BASIC is seriously rusty but...
In BlitzMax the side :| LEFT_SIDE is equivalent to Let side = side | LEFT_SIDE. The vertical bar is a bitwise or operator. Whats the BASIC bitwise or operator nowadays? simply 'OR'?

So using the 'bitwise or' link as an example along side your algorithm, it shows 4 bits. You could think of each 'bit' as a flag to represent each of the 4 sides, if the side has been checked then its bit will become 1, if it hasnt been checked then it will be 0.

As already mentioned, variable names should really be named in a way that describe what they are used for and using a descriptive variable name is easier than trying to remember numbers or letters. You already have your own system for this, but it only works for you. If you want to show other people how an algorithm works then descriptive names are a must have! Comments alone are not enough, honestly.

Back to 'binary bits'... so that you don't have to remember that a 'bit set' value is a particular value, ie bit1 ( when set ) has a value of 1, and bit2 has a value of 2, bit3 has a value of 4 and bit4 has a value of 8 you can create a variable name to represent each bit value, hence LEFT_SIDE = 1, RIGHT_SIDE = 2, TOP_SIDE = 4, BOTTOM_SIDE = 8.

Using the 'bitwise or' is kinda like including the bit value into another variable/value. It doesn't 'add' the value! very important! it will only include that bit value into the destination value, and if that bit is already set then there is no change. To help understand these, there are what are called 'binary operator truth tables' that are used for binary logic operations. Some programming languages have more binary operators than others, it all depends on the language creator which ones are in the language.

You already have is a variable named 'sides' and you want to check if the 4 sides have been checked. Each time a side is checked take its 'bit' value and store it in the 'sides' variable. You do that by using the 'bitwise or' operator, which as said above will include the bit thats represented by either LEFT_SIDE, RIGHT_SIDE etc into the value of 'sides' .

You can then have a value that represents when ALL sides have been checked, ie when all bits have been set. That value in this case will be 'binary of 1111', 'hex F' or 'decimal 15'. So create a Const ALLSIDES:Int = 15 and when you want to check if all sides have been checkd you could simply write 'Until sides = ALLSIDES'. Even that one line change alone makes that line self documenting, you can look at that one single line and read exactly what its doing without looking at any other piece of code. You know what the loop is trying to achieve. I might even go a little further so instead of just 'sides' I'd call it 'SidesChecked' or similar. Which then becomes Until SidesChecked = ALLSIDES. So much easier to understand than 'Until c1+c2+c3+c4=4', and it's also arguably faster too as the cpu isn't doing the adding arithmetic every time it hits this line.

Ultimately using this technique throughout all of your code will make it much more readable to yourself and for everyone else that you want to show how your code works.

Hope it helps!


steve_ancell(Posted 2016) [#9]
This is quite good and all that but is there a way to generate for both legs in and legs out?, as in 2 states of animation.


steve_ancell(Posted 2016) [#10]
When I see something as cool as what you've done here, I just had to go and try it for myself. I just knocked up something simple but similar in Blitz3D.




dw817(Posted 2016) [#11]
Hi Col. Thanks for this lesson. No, I mean that. I wish more people would let me know what's going on out there. Yes, I program old-school, but I =DO= get the job done and have made some pretty neat things ! :)

Let's see ... Okay, I'm not even familiar with | . To me with a variable that represents it is a BYTE variable, a la "cond|" which is different from "cond" which is a long integer.

Minju ! These are not the case in BlitzMAX. Someone was kind enough to point earlier the following:

' @ - Byte
' x@ is the same as x:Byte

' @@ - Short
' x@@ is the same as x:Short

' % - Int
' x% is the same as x:Int

' %% - Long
' x%% is the same as x:Long

' # - Float
' x# is the same as x:Float

' ! - Double
' x! is the same as x:Double

' $ - String
' x$ is the same as x:String

Now, I knew strings ($), float (#), and int (%), but these others are definitely alien to me. There are no bitwise operators in BlitzMAX (near as I can tell). You can't have

a=bttst(b,4) which would return the 5th bit of value b.

In GFA anyways, you could use (!) to represent a bit variable. Make an array and go to town.

DIM flags!(7),v

flags!=v (where v is a value from 0-255), and then you could read flags!(7) to pull out the 8th bit (high bit) of v. Neat stuff !

This sides stuff is confusing though. If you uniquely wanted to handle 4-sides of a square, wouldn't it be easier just to have 4-variables, say, s1, s2, s3, s4 and do your mathematical wizardry around those then assign an array 1, 2, 4, 8, which is what I think you are saying ?

I don't like to do tricks like that when =I= have to understand the code myself. I still use a=1-a to flip a 'switch.' I'm certain you could use a:| (if I'm reading that right), and it would do the same thing.

But a=1-a makes a lot more sense to me, and those new programmers out there, it can also be understood. It's only when I got to B4GL did I see that there were variable shortcuts. A-=1 and a+=1 to increase a variable instead of the usual a=a-1 and a=a+1, which I'm more familiar with.

This Allsides seems very wasteful to me. Much easier just to create 4-variables and go with it.

Now, I can understand if I needed say only a C to exist, that is a [ ] |_| and |'''| then my 4-variables would come in awful handy.

if (c1=1 and c2=1 and c3=1 and c4=0)or(c1=1 and c2=1 and c3=0 and c4=1)or(c1=1 and c2=0 and c3=1 and c4=1)or(c1=0 and c2=1 and c3=1 and c4=1)then ... we have a pocket to put data in (useful for Match-3 games).

Sure, you can get tricky and say:
c=0
For k=0 To 7
        For n=0 To 3
          If inv[n,k]
            If n=0 Then c1=1 ' tricky, ensure that critter
            If n=3 Then c2=2 ' touches all 4-sides, no 6x8 or
            If k=0 Then c3=4 ' 8x7 sprite, always 8x8
            If k=7 Then c4=8
          EndIf
        Next
      Next


And then look for your 'cup' from totals 7, 14, 11, or 13, but for legibility, go with the original: if (c1=1 and c2=1 and c3=1 and c4=0)or(c1=1 and c2=1 and c3=0 and c4=1)or(c1=1 and c2=0 and c3=1 and c4=1)or(c1=0 and c2=1 and c3=1 and c4=1). Someone can look at this and see exactly what you are doing without having to add up numbers in their head.

Anyone can get tricky in code and make it smaller and illegible, but you want people (including yourself) to be able to understand the code later. And, someone did suggest I place REMARKS in my code, and I am doing that now, and I must admit, it does help legibility and doesn't slow down the execution.

As for understanding my code, tweak it ! That's what I learned when I typed this, the first computer program I ever entered when I was 8-years old.

http://willus.com/trs80/?-a+1+-p+126050+-f+1

Sure I didn't understand it. Took me 4 tries to type it the right way. But once I ran it, I wanted to change it. I modified numbers, variables, all kinds of things. I tweaked it, and I think I learned more than if someone tried to explain to me all the commands instead.

In truth, I've read very few books on programming. I'm always learning from example code, have all my life - and, as life turns around, now I am the one providing source code, hopefully so a younger me out there can copy the code (they don't have to type it anymore) and TWEAK the code and learn from it to see how it changes. :)


dw817(Posted 2016) [#12]
Steve, I can't get this to run on my computer. It crashes on:

SetBuffer BackBuffer()

with, "Compile Error - Identifier 'SetBuffer' not found."

Oh, and as for alien legs. I did something like this back on Apple with vectors. I would choose a random vector and move it UDLR randomly in one direction to give the 'critter' some movement. It was for a RPG tho.

I could apply that here too I suppose.

I was thinking of rewriting "Ceiling Zero" in BlitzMAX and posting the source using perfectly random and animated critters from the code above.



That's one of my favorite topview shooting games from Apple. And there would be a lot more than just 4-critters bopping about, but a whole mess of 'em. :)


Matty(Posted 2016) [#13]
That's because SetBuffer Backbuffer() is for blitz3d (as Steven mentioned in his post)....it's not a blitzmax set of source code.


steve_ancell(Posted 2016) [#14]
@dw817:

Just as Matty just stated it's Blitz3D, I thought I would see how easy it is for non-BlitzMax users to duplicate.

Good work BTW! ;)


dw817(Posted 2016) [#15]
I have yet to be able to download a copy of Blitz3D, Matty. I try and just get a blank white page.



If someone could post a URL where I can download it, I would appreciate it.


steve_ancell(Posted 2016) [#16]
@dw817:

To download Blitz3D you need to do the following...

From your account on here navigate to: Account->Register product then select Blitz3D from the drop-down menu. Finally type FREEBLITZ3D in the Registration code field.

To download navigate to: Account->Product updates and then scroll down until you can find the installation files and updates.


dw817(Posted 2016) [#17]
Thanks, Steve. I'm pretty good with math (sometimes).

Reading your descript for downloading this language. Wholly smokes ! Not everyone is going to know that ! :D If you work for Blitz, you might let them know that's a bit of work for people just discovering the website for the first time, let alone someone like me (who is supposed to be) fairly knowledgeable.

In this case, I wasn't. Attempting ... Got it up. Wow, that is one small font they are using. Can't seem to find configuration to make it bigger ? Hmm ...

Trying out your code in it.

Does the same invader every time. Oh, hit SPACE to see next. Got it. Still, you need to seed random. I like the rapid compilation though. A lot faster then BlitzMAX. Pretty sharp work there Steve ! :)

Compiling to EXE, running. OUCH, it hardware tries to acquire 800x600. Nasty - I never did like that. Can you write code in B3D where it uses the current display and full-screen except maintaining the task buttons below in Windows ?

Also, how do you change the font and colors for the IDE ? Checking more ... where is HELP on commands ?


steve_ancell(Posted 2016) [#18]
I never did like that. Can you write code in B3D where it uses the current display and full-screen except maintaining the task buttons below in Windows

If you mean can Blitz3D use the desktop resolution then yes it can, just use the command Graphics 0, 0 as far as I remember. My Blitz3D skills have become a little rusty since I switched to Monkey-x a couple of years back, but I could get back into it if I really needed to.


dw817(Posted 2016) [#19]
Hmm ... "Graphics 0,0" It's not that. Anyways, I'm supposed to just be talking about BlitzMAX and here I am, trying out a new flavored jellybean. So far it's earwax as near as I can tell.

I would need more dox to really look it over proper and see its merit. Got your code to run though. Yep, you are using a LOT of pixels, cut down and let the BLACK area give more definition to your aliens. Try this change:
			colourState=Rnd(3)
			If colourState<2
				Color 0,0,0
			ElseIf colourState=2
				Color red1,green1,blue1
			ElseIf colourState=3
				Color red2,green2,blue2
			EndIf
Ohh ! Nossir ! You can't hit CTRL-Z to undo ALL typed elements, only the last character like Notepad does ?? Owie !

I betcha someone wrote a really snazzy B3D IDE I'm not aware of to replace this one. :D


TomToad(Posted 2016) [#20]
A bit on bitmasking:

| is a bitwise Or
& is a bitwise And

To set a bit , use Value | 2^Bit
So to set bit 6, you would type Value = Value | Int(2^6), or Value :| 64 you need to cast the ^ operator to Int as it returns a float

To clear a bit, use Value & ~(2^Bit)
So to clear bit 6, Value = Value & ~Int(2^6) or Value :& ~64

To test a bit, use Value & 2^Bit, a 0 means the bit is clear, and non 0 means it is set,
SuperStrict

Local Value:Int = 0
Print "Current bits = "+Bin(Value)

Value = Value | Int(2^6) 'set bit 6 the old fashioned way
Print "~nCurrent bits = "+Bin(Value)

Value :| 16 'Set bit 4 the BlitzMax way (2^4 = 16)
Print "~nCurrent bits = "+Bin(Value)

Value :| 16 'to show that setting the bit again doesn't affect the value if the bit is already set
Print "~nCurrent bits = "+Bin(Value)

Value = Value & ~Int(2^6) 'Clear bit 6
Print "~nCurrent bits = "+Bin(Value)

Print "Bit 6 = "+(Value & 64 <> 0) 'Test if bit 6 is set (2^6 = 64)
Print "Bit 4 = "+(Value & 16 <> 0) 'Test if bit 4 is set (2^4 = 16)



TomToad(Posted 2016) [#21]
Also to add, To set or clear more than one bit at a time, you can combine the values. So to set bit 2 and 0, You can use 4 + 1, or 5. Value :| 4 | 1 or Value :| 5
By using constants, you can set/clear based on name
'Partial source code, do not compile :)
Const NORTH = 2^0 ' = 1
Const EAST = 2^1 ' = 2
Const SOUTH = 2^2 ' = 4
Const WEST = 2^3 ' = 8

Local Walls:Int = 0 'Which sides of the room has walls?
Walls :| NORTH | WEST 'set the North and West walls to true

If Walls & NORTH 'Check if there is a wall to the north
    Print "You cannot go that way"
Else
    Move(NORTH)
End If



col(Posted 2016) [#22]
To compliment what TomToad has just posted ( EDIT: Post#20 )...

if you're using the standard BMax editor then in the main toolbar to the far right there is a little house and 2 arrow icons. The house is the documentation 'Home' icon, the arrows are for navigating back and forth through the help pages that you've looked at it, in the same way as browsing web pages.

Some information regarding the operators that Brucey and TomToad have mentioned are in
Home->Language Reference->Variables, and scroll down 'Assigning variables'.


BlitzSupport(Posted 2016) [#23]
Just to say, really cool results, whatever the methods!


steve_ancell(Posted 2016) [#24]
@dw817:

I would like to make a suggestion if I may. Download the IDEal Blitz3D editor, it helps a lot. Keep up with the good work in BlitzMax, I downloaded and installed BlitzMax a while back and will probably have a go at using it for some projects. From what I see so far it seems very similar to Monkey-X.


dw817(Posted 2016) [#25]
Col, I looked. I didn't see any bitwise operations.

Hi Tom:

Hmm ... I think you're showing me how to write a bit reader and writer.



Yeah, Xorbit is not so good. Is there an easier way to get that down to 1-line of code ?

Steve, I'll check out the IDEal Blitz3D editor.

BlitzSupport, glad you like it ! I may use this later and animate 'em besides ! :)

.. ?? Hoah, that is one nice IDE, Steve !

Is there anything like this for BlitzMAX ?