#1✎ 5builderofthecakeFor example, in python, you can say
class Apple:
def __init__(self, color, x, y):
self.color = color
self.x = x
self.y = y
def beRainbow(self,color):
self.color = 'Rainbow'
apple1 = Apple('Red',12,23)
apple2 = Apple('Green',14,23)
And then apple1.color is 'Red', and I can make apple1.color equal 'Rainbow' by doing apple1.beRainbow()
Is there some sort of workaround to this? Do you have to use arrays or something? Thank you for any help, I really like being able to make programs on my 3ds, I am just having some difficulty with these concepts.
Posted
#3✎ 19thatguyIntermediate ProgrammerI can make programs, but I still have trouble here and there. Programming StrengthVideo GamesI like to play video games!HobbiesNight PersonI like the quiet night and sleep late.Express YourselfYou can do that be doing something like this:
ACLS
RAINBOW=TRUE
@MAINLOOP
WAIT 10
GCLS
IF RAINBOW==FALSE THEB GPUTCHR 0,0,"APPLE",RGB(255,0,0) ELSE GPUTCHR 0,0,"APPLE",RGB(RND(255),RND(255),RND(255)
GOTO @MAINLOOP
By setting the rainbow boolean to be false it is going to display the text in red. If there is anything you don't understand feel free to ask I am probaly not avaible for the time being but I will try to answer as soon as possible.
Ps. I recomend you to watch petiteprofessor smilebasic tutorials on youtube they are very helpfull to people new to the progamming language.
Posted
Edited
by thatguy
#4✎ 5builderofthecakeOkay, so I did some experimenting, and I found a workaround, but it's quite messy I think, hopefully I'll be able to get better at using arrays like this by looking more at the sample programs.
So I wanted 10 apples to fall to the ground, each with their own x and y values, so I was able to do this
SIZE = 10 'Number of apples
DIM AX[SIZE], AY[SIZE] 'Arrays for the apple coords
so now that there are variables for each apple. Then I can use a for loop to check them all
FOR I=0 TO SIZE-1
INC AY[I]
IF AY[I]<=28 THEN 'If within y limit of screen
LOCATE AX[I],AY[I]
PRINT("A")
ELSE
resetApple(I) 'At random time puts apple I back to top at random X position
ENDIF
NEXT
Hopefully I'll be able to get a better grip of this kind of organization, it just seems clunky, but it somewhat resembles how EX7ALIEN is able to manage the enemy invaders without using objects.
Posted
Edited
by builderofthecake
#5✎ 922snail_HelperReceived for being very helpful around SmileBASIC SourceAchievementsOSP Contest 2 Contest ParticipantI participated in the second SmileBASIC Source OSP Contest!Night PersonI like the quiet night and sleep late.Express YourselfYou can't make real objects in SB; it isn't a language feature. Using arrays to be like "pools" for object data isn't a bad idea. If you're working with sprites, they actually do have their own features that you can apply to be really similar to "objects" but it depends on what exactly you're doing.
The sample programs are… okay. They aren't exactly shining examples of what SB is truly capable of (or even how to write good SB code) since many of them are PTC conversions (and others were slightly botched by localization and updates.)
Posted
#6✎ 922snail_HelperReceived for being very helpful around SmileBASIC SourceAchievementsOSP Contest 2 Contest ParticipantI participated in the second SmileBASIC Source OSP Contest!Night PersonI like the quiet night and sleep late.Express Yourself
This is a decent approach if you absolutely can't live without something like an object, but they aren't "real" and they aren't very efficient, either. I haven't maintained this library in a while.
Posted
You can't make real objects in SB; it isn't a language feature. Using arrays to be like "pools" for object data isn't a bad idea. If you're working with sprites, they actually do have their own features that you can apply to be really similar to "objects" but it depends on what exactly you're doing.
The sample programs are… okay. They aren't exactly shining examples of what SB is truly capable of (or even how to write good SB code) since many of them are PTC conversions (and others were slightly botched by localization and updates.)
I know you can't make real objects, but there has to be a way around that, right? People can still make games and stuff, I just don't get what they are doing to work around this incapability. If you wanted multiple entities in a dungeon crawler, how would you manage every entity's X and Y position and HP for example? In any other language I would use a class, but what is the convention for SB? (Sorry for all the questions x.x)
Posted
#8✎ 103niconiiVideo GamesI like to play video games!HobbiesExpert ProgrammerProgramming no longer gives me any trouble. Come to me for help, if you like!Programming StrengthDrawingI like to draw!Hobbies
I know you can't make real objects, but there has to be a way around that, right? People can still make games and stuff, I just don't get what they are doing to work around this incapability. If you wanted multiple entities in a dungeon crawler, how would you manage every entity's X and Y position and HP for example? In any other language I would use a class, but what is the convention for SB? (Sorry for all the questions x.x)
An array for entity HPs, an array for entity X positions, and an array for entity Y positions would be the simplest way to do it.
Posted
#9✎ 166MochaProbablyExpert ProgrammerProgramming no longer gives me any trouble. Come to me for help, if you like!Programming StrengthNight PersonI like the quiet night and sleep late.Express YourselfDrawingI like to draw!Hobbies
I know you can't make real objects, but there has to be a way around that, right? People can still make games and stuff, I just don't get what they are doing to work around this incapability. If you wanted multiple entities in a dungeon crawler, how would you manage every entity's X and Y position and HP for example? In any other language I would use a class, but what is the convention for SB? (Sorry for all the questions x.x)
An array for entity HPs, an array for entity X positions, and an array for entity Y positions would be the simplest way to do it.
You could do what i’m doing and store it in one string array, and read the data listed above from each string. Much more space efficient.
Posted
#10✎ 166012Me21Head AdminThird YearMy account is over 3 years oldWebsiteSyntax HighlighterReceived for creating the code syntax highlighter on SBSNight PersonI like the quiet night and sleep late.Express Yourself
I know you can't make real objects, but there has to be a way around that, right? People can still make games and stuff, I just don't get what they are doing to work around this incapability. If you wanted multiple entities in a dungeon crawler, how would you manage every entity's X and Y position and HP for example? In any other language I would use a class, but what is the convention for SB? (Sorry for all the questions x.x)
An array for entity HPs, an array for entity X positions, and an array for entity Y positions would be the simplest way to do it.
You could do what i’m doing and store it in one string array, and read the data listed above from each string. Much more space efficient.
I know you can't make real objects, but there has to be a way around that, right? People can still make games and stuff, I just don't get what they are doing to work around this incapability. If you wanted multiple entities in a dungeon crawler, how would you manage every entity's X and Y position and HP for example? In any other language I would use a class, but what is the convention for SB? (Sorry for all the questions x.x)
An array for entity HPs, an array for entity X positions, and an array for entity Y positions would be the simplest way to do it.
Okay, thank you!
Posted
#12✎ 125amihartIf you want a much cleaner way to do it, you could setup your own object-like system like this:
VAR MAX_ENTITIES=100
DIM ENTITIES[4, MAX_ENTITIES]
'Add a new entity
DEF NEW_ENTITY(X, Y, HP)
'Search for empty space to store an entity
VAR I
FOR I=0 TO MAX_ENTITIES-1
IF ENTITIES[0, I]==FALSE THEN
BREAK
ENDIF
NEXT
'If no empty space was found, return -1
IF I==MAX_ENTITIES THEN
RETURN -1
ENDIF
'Store the entity and return its address.
ENTITIES[0, I]=TRUE
ENTITIES[1, I]=X
ENTITIES[2, I]=Y
ENTITIES[3, I]=HP
RETURN I
END
'Destroy an entity
DEF DESTROY_ENTITY E
ENTITIES[0, E]=FALSE
END
'Accessors
DEF GET_X(E)
RETURN ENTITIES[1, E]
END
DEF GET_Y(E)
RETURN ENTITIES[2, E]
END
DEF GET_HP(E)
RETURN ENTITIES[3, E]
END
'Mutators
DEF SET_X E, X
ENTITIES[1, E]=X
END
DEF SET_Y E, Y
ENTITIES[2, E]=Y
END
DEF SET_HP E, HP
ENTITIES[3, E]=HP
END
'Main code
VAR PLAYER=NEW_ENTITY(25,25,100)
PRINT "Player stats..."
PRINT " X: " + STR$(GET_X(PLAYER))
PRINT " Y: " + STR$(GET_Y(PLAYER))
PRINT " HP: " + STR$(GET_HP(PLAYER))
Here we can create an entity called "PLAYER" with the X and Y values 25, 25, and HP 100. We can get these values with our accessors. Such as "GET_HP(PLAYER)" will return the player's HP, and we can change them with our mutators, such as "SET_Y PLAYER, 5" will change the player's Y value to 5.
We can make as many entities as we want up until MAX_ENTITIES.
There's a fourth property for each entity here, that is the "alive" property. A created entity has that value initially set to true, and it is always true until the entity is destroyed. When you go to create an entity, it searches for the first slot where a destroyed entity is located by checking their "alive" property, and it stores the entity there.
This will be fast enough for most purposes, but if you're dealing with thousands of entities, creating entities this way can be pretty slow. A much quicker way to do it would be to keep a "journal".
VAR MAX_ENTITIES=100
DIM ENTITIES[4, MAX_ENTITIES]
VAR ENTITIES_SIZE=0
VAR JOURNAL[.]
'Add a new entity
DEF NEW_ENTITY(X, Y, HP)
VAR ID
IF LEN(JOURNAL)>0 THEN
ID=POP(JOURNAL)
ELSEIF ENTITIES_SIZE!=MAX_ENTITIES THEN
ID=ENTITIES_SIZE
INC ENTITIES_SIZE
ELSE
RETURN -1
ENDIF
'Store the entity and return its address.
ENTITIES[0, ID]=TRUE
ENTITIES[1, ID]=X
ENTITIES[2, ID]=Y
ENTITIES[3, ID]=HP
RETURN ID
END
'Destroy an entity
DEF DESTROY_ENTITY E
'Store the entity and return its address.
ENTITIES[0, E]=FALSE
IF E==ENTITIES_SIZE-1 THEN
DEC ENTITIES_SIZE
ELSE
PUSH JOURNAL, E
ENDIF
END
This journal basically logs every time an entity is destroyed, so when you go to create a new entity, you can immediately know where to put it just by looking at the journal. Creating entities the first way is linear time O(n) since it has to search potentially the entire dimension of the array while keeping a journal makes it constant time O(1) since there is no searching, you can just look at the journal and immediately know where to store the next entity.
Posted
Edited
by amihart
#13✎ 166MochaProbablyExpert ProgrammerProgramming no longer gives me any trouble. Come to me for help, if you like!Programming StrengthNight PersonI like the quiet night and sleep late.Express YourselfDrawingI like to draw!Hobbies
I know you can't make real objects, but there has to be a way around that, right? People can still make games and stuff, I just don't get what they are doing to work around this incapability. If you wanted multiple entities in a dungeon crawler, how would you manage every entity's X and Y position and HP for example? In any other language I would use a class, but what is the convention for SB? (Sorry for all the questions x.x)
An array for entity HPs, an array for entity X positions, and an array for entity Y positions would be the simplest way to do it.
You could do what i’m doing and store it in one string array, and read the data listed above from each string. Much more space efficient.
But why?
It was really easy, i got learn more about strings, and i could hold all the needed data in one array.
Posted
If you want a much cleaner way to do it, you could setup your own object-like system like this:
VAR MAX_ENTITIES=100
DIM ENTITIES[4, MAX_ENTITIES]
'Add a new entity
DEF NEW_ENTITY(X, Y, HP)
'Search for empty space to store an entity
VAR I
FOR I=0 TO MAX_ENTITIES-1
IF ENTITIES[0, I]==FALSE THEN
BREAK
ENDIF
NEXT
'If no empty space was found, return -1
IF I==MAX_ENTITIES THEN
RETURN -1
ENDIF
'Store the entity and return its address.
ENTITIES[0, I]=TRUE
ENTITIES[1, I]=X
ENTITIES[2, I]=Y
ENTITIES[3, I]=HP
RETURN I
END
'Destroy an entity
DEF DESTROY_ENTITY E
ENTITIES[0, E]=FALSE
END
'Accessors
DEF GET_X(E)
RETURN ENTITIES[1, E]
END
DEF GET_Y(E)
RETURN ENTITIES[2, E]
END
DEF GET_HP(E)
RETURN ENTITIES[3, E]
END
'Mutators
DEF SET_X E, X
ENTITIES[1, E]=X
END
DEF SET_Y E, Y
ENTITIES[2, E]=Y
END
DEF SET_HP E, HP
ENTITIES[3, E]=HP
END
'Main code
VAR PLAYER=NEW_ENTITY(25,25,100)
PRINT "Player stats..."
PRINT " X: " + STR$(GET_X(PLAYER))
PRINT " Y: " + STR$(GET_Y(PLAYER))
PRINT " HP: " + STR$(GET_HP(PLAYER))
Here we can create an entity called "PLAYER" with the X and Y values 25, 25, and HP 100. We can get these values with our accessors. Such as "GET_HP(PLAYER)" will return the player's HP, and we can change them with our mutators, such as "SET_Y PLAYER, 5" will change the player's Y value to 5.
We can make as many entities as we want up until MAX_ENTITIES.
There's a fourth property for each entity here, that is the "alive" property. A created entity has that value initially set to true, and it is always true until the entity is destroyed. When you go to create an entity, it searches for the first slot where a destroyed entity is located by checking their "alive" property, and it stores the entity there.
This will be fast enough for most purposes, but if you're dealing with thousands of entities, creating entities this way can be pretty slow. A much quicker way to do it would be to keep a "journal".
VAR MAX_ENTITIES=100
DIM ENTITIES[4, MAX_ENTITIES]
VAR ENTITIES_SIZE=0
VAR JOURNAL[.]
'Add a new entity
DEF NEW_ENTITY(X, Y, HP)
VAR ID
IF LEN(JOURNAL)>0 THEN
ID=POP(JOURNAL)
ELSEIF ENTITIES_SIZE!=MAX_ENTITIES THEN
ID=ENTITIES_SIZE
INC ENTITIES_SIZE
ELSE
RETURN -1
ENDIF
'Store the entity and return its address.
ENTITIES[0, ID]=TRUE
ENTITIES[1, ID]=X
ENTITIES[2, ID]=Y
ENTITIES[3, ID]=HP
RETURN ID
END
'Destroy an entity
DEF DESTROY_ENTITY E
'Store the entity and return its address.
ENTITIES[0, E]=FALSE
IF E==ENTITIES_SIZE-1 THEN
DEC ENTITIES_SIZE
ELSE
PUSH JOURNAL, E
ENDIF
END
This journal basically logs every time an entity is destroyed, so when you go to create a new entity, you can immediately know where to put it just by looking at the journal. Creating entities the first way is linear time O(n) since it has to search potentially the entire dimension of the array while keeping a journal makes it constant time O(1) since there is no searching, you can just look at the journal and immediately know where to store the next entity.
Thank you for the tip! I never thought of doing it like that!
Posted
#15✎ 44OChunksHDNight PersonI like the quiet night and sleep late.Express YourselfVideo GamesI like to play video games!HobbiesIntermediate ProgrammerI can make programs, but I still have trouble here and there. Programming StrengthHere's how I've been taught how to make an array...
ACLS
DIM ARRAY[X,Y]'X AND Y ARE THE NUMBER OF THINGS YOU WANT IN EACH DIMENSION, SO LETS SAY 4 BY 4
RESTORE @ARRAY
FOR I=0 TO X
FOR J=0 TO Y
READ A' READS THE DATA
ARRAY[X,Y]=A
NEXT
NEXT
@ARRAY
DATA 1,4,77,0
DATA 1,4,2,8
DATA 3,8,7,99
DATA 1,34,22,555
Posted
#16✎ 131raimondzFirst WeekJoined in the very first week of SmileBASIC SourceWebsiteExpert ProgrammerProgramming no longer gives me any trouble. Come to me for help, if you like!Programming StrengthNight PersonI like the quiet night and sleep late.Express YourselfHave you tried lowerdash or N#? Maybe you could use them to simulate OOP.
Posted
#17✎ 166MochaProbablyExpert ProgrammerProgramming no longer gives me any trouble. Come to me for help, if you like!Programming StrengthNight PersonI like the quiet night and sleep late.Express YourselfDrawingI like to draw!HobbiesString Array Storage System (S.A.S.S)
ACLS
DIM OBJ$[100]
DEF SET_OBJ ID,X,Y
OBJ$[ID] = STR$(X) + “,” + STR$(Y)
END
DEF READ_OBJ(TYPE$,ID)
DIM C[1]
FOR I=0 TO LEN(OBJ$[ID])
IF MID$(OBJ$[ID],I,1) == “,” THEN PUSH C,I+1
NEXT
IF TYPE$ == “X” THEN RETURN VAL(MID$(OBJ$[ID],C[0],C[1]))
IF TYPE$ == “X” THEN RETURN VAL(MID$(OBJ$[ID],C[1],LEN(OBJ$[ID])))
END
DEF EDIT_OBJ TYPE$,ID,VALUE
DIM CC[0]
FOR I=0 TO LEN(OBJ$[ID])
IF MID$(OBJ$[ID],I,1) == “,” THEN PUSH CC,I+1
NEXT
IF TYPE == “X” THEN OBJ$[ID] = SUBST$(OBJ$[ID],0,LEN(STR$(READ_OBJ(“X”,ID))),STR$(VALUE))
IF TYPE == “Y” THEN OBJ$[ID] = SUBST$(OBJ$[ID],CC[0],LEN(STR$(READ_OBJ(“Y”,ID))),STR$(VALUE))
END
From here you can create, edit, and read object data from a single string, no hassle required. The only thing though is that any value over 10 digits will make things not what they are, because SmileBasics way of handling things, but those high of values are usually uncommon for objects.
Demo code :
SET_OBJ 1,100,10
PRINT READ_OBJ(“X”,1)
EDIT_OBJ “X”,1,999
PRINT READ_OBJ(“X”,1)
What’s cool about this system is that you can easily add more data to each object and use the same array. If you want have 100 objects defined you don’t need 3 100 slotted arrays, you’ll only need 1 100 slotted arrays. This is super useful if each object needs lots of data attached to it.
EDIT : Amiharts system is better (I worked too hard again, even when there was a simple solution.... time to restructure my object orientated system thing...)
Posted
Edited
by MochaProbably
While this technically works a method like this should only be used for saving/loading data (such as JSON), not manipulating data in real-time in something like a video game. It is pretty slow, and the more complex your object is the slower it will take to parse it.
Posted
#19✎ 160DFrostExpert ProgrammerProgramming no longer gives me any trouble. Come to me for help, if you like!Programming StrengthOne other example is this:
DEF Entity()
DIM OBJECT[8]
OBJECT[0]=0'SP#
OBJECT[1]=200'X
OBJECT[2]=120'Y
OBJECT[3]=0'Z
OBJECT[4] = 0'U
OBJECT[5] = 0'V
OBJECT[6] = 16'W & H
OBJECT[7] = 1'SCALING FACTOR
RETURN OBJECT
END
DEF RENDER ENTITY
SPSET ENTITY[0],ENTITY[4],ENTITY5],ENTITY[6],ENTITY[6]
SPOFS ENTITY[0],ENTITY[1],ENTITY[2],ENTITY[3]
SPSCALE ENTITY[0],ENTITY[7],ENTITY[7]
END
Posted
#20✎ 26incvoidI got very similar.
but its all very manual. So inside the "class" you have to keep putting the prefix before it... very bloated and tedious.
I used an array for each member of the object and a count, and some have strings to help do field to text translation, think I even used a call to var to lookup fields. But seeing as most classes have the same fields such as count/type/name or whatever... I kept the class prefix in the name so kinda useless to try to generalize the field access, smilebasic likes unique named.I gave most objects their own "out" functions so they could format their own debug outs.
F=VAR(TI_$[I])'where i is the field
F[object_index]' such as F[player] or F[T] I use T as "this"
I was working with a bunch of fields, like seconds, minutes, hours that were overflowing into each other so I liked to think of things as F and F2 instead of seconds/minutes and it made debug'ing a lot easier.
I=TI_FIELDS-1
F=VAR(TI_$[I])
F2=VAR(TI_$[I-1])
TI_OFLOW T,F,F2
I=TI_FIELDS-2
F=VAR(TI_$[I])
F2=VAR(TI_$[I-1])
TI_OFLOW T,F,F2
I know its ugly but it let me manually debug things, had to unroll a for loop etc. Hope it makes sense...or shows how not to do things at the least ;)
In hindsight it would of been nice to say .sec .min .hour when writing the time handling, made it easier to read etc.
I didn't care to put any object limits in, just push things ontop of their array. do a copy for array to array, if I recall, sb wont' push arrays onto arrays, have to mem copy. which means you have to keep track of where an objects portion of the array begins and ends.
Its all indices. an index that is used by functions, generally one index will work with all the members. battling between what you can read and type in before forgetting how to read an objects value.
all that goes in a separate slot from my main program.
load "PRG1:LIBRARYNAME1",FALSE
USE 1
GOSUB "1:@DEFDT"
VAR CUR=NEWTI(2016,9,20,2,0,0):?"CUR=";CUR
TI_OUT CUR 'will output the time in the "CUR" object
The idea is that being in a separate slot it is out of my way and I can use the time fields with a few update calls or setting new time and now I got timers and a sorta minimal calender support.
Programming in SB is always a tradeoff of what inputs fast, holds some value to re-reading the code, and what keeps good namespace.. obviously I'd run out of namespace as it quickly turns into abbreviations for object names but ohwell.
No inheritance, but objects can have "references" to other objects.. its just an index afterall.
If you are dealing with AX and AY array for aliens. sure that works. and it is very easy to input. You got an "object" or "index" you just need to write the functions on what to do with it. so you get the nice function names that are backwards of the dot operator version
Apple1.set_color("red")
'turns into
AppleSet_color(Apple1,"red")
the goal of object based is to get it so you don't have to type as much, and can forget the nuances of array definition and access... so using the libraries seems the way to go when your objects differ so much from each other that they need their own unique fields that aren't useable by other functions etc.
Posted
Edited
by incvoid