Reply to topic  [ 3 posts ] 
 The Project Bane Tutorial Thread 
Author Message
Level 22
Level 22
User avatar

Cash on hand:
175,593.20
Posts: 2257
Joined: Sat Nov 17, 2012 11:10 am
Location: SR388
Group: Special Access
Post The Project Bane Tutorial Thread
In this thread I will list out tutorials for using blender 2.49b and python 2.6.2 to make video games.

I may edit the order of tutorials from easiest to hardest at a later time.

_________________
mepsipax

Image

got any?

His name is not Robert Paulsen, His name is Gregory Matthew Bruni, he won so hard.

_________________
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.


Sun Jul 31, 2016 7:43 pm
Profile E-mail
Level 22
Level 22
User avatar

Cash on hand:
175,593.20
Posts: 2257
Joined: Sat Nov 17, 2012 11:10 am
Location: SR388
Group: Special Access
Post Re: The Project Bane Tutorial Thread
Tutorial: Custom Save Files

first you need to know whether your save file is going to be a document or a database; each has their own usage which can be important to game design (however for most databases you can just keep them in game as set variables).


Document: a document is a simple list of entries, each one has it's own line in the file, it's great for saving things like; Player Location, HP at save, Magic at save, how much money you have, what item(s) is(are) equipped, what items/abilities you have unlocked, what secrets you've seen etc.

to write a document first you are going to define your values, it's best to keep your values in virtual memory, that is 'open in the program not a file' as much as possible otherwise all those read and write operations are going to fry your hard disk.

I'll be honest with you, most game developers do not even give this one fuck. they will be happy to sacrifice your hard disk's life span with mass read/write operations that could have been better handled as virtual memory writes and reads.

So as a good model only write or read from a file when absolutely necessary. For example write a document reader (what we will do here today) that loads the information from the document when you start the game, it only needs to recheck this document if there has been a change in the document (such as the user Saved with less arrows and exited that save slot and reopened it). At all other times it should function off what it read at start and not recheck the save file for the remainder of the game until a save function is called.

Lets do the basic blender python thing:

#begin script#

cont = GameLogic.getCurrentController() #you can call it 'c' or 'cunt' too it's entirely up to you. this gets the controller on which your script is activating from, hint; for debugging you can do 'print cont' to see the name of the controller that's fucking up.
own = cont.owner # this is the game object that this script is running on, NOT it's NAME! the actual object! if you like you can call it obj = cont.owner or 'o' or 'ob' but stay away from using 'OB' never do it because it's used as a prefix to object names and in complicated code could fuck the shit up. if you want the name of the object you do own.name or own.getName().

#now lets define some shit.
SHIT = cont.sensors[0] # you can define it as anything, I however try to keep my terms and names uniform so I don't get confused, ALWAYS NAME SENSORS OR ACTUATORS WHICH ARE ATTACHED TO A SCRIPT! if you don't know what to name it, either use a summary such as ATKSens or use obscenities. I didn't say what the sensor is cause it doesn't matter, at this point it could be anything

HP = own.get("HP") #This property is obvious, it will be a number or a list of numbers or a phrase in rare conditions. this is a property, you cannot edit it directly (great for anti-hax), notice the use of 'own' and .get() using .get on a game object will return whatever it is you tell it to look for, in this case by giving it a property name 'HP' I'm telling it I want it to return the value of that property as plain text.
MAG = own.get('Magic')
MUNAHY = own.get('Gold')
BOOMSTICKS = own.get('Arrows')
ITEMEquip = own.get('EquipItem')

# a quick note before you go further, own.get is great for getting information on the fly, but only for that frame on which the script has run, if changes happened to the property after the script ran it will not record them. to record chang-able values you'll need to use a property actuator's value field as those are in live virtual memory outside of any given frame. like this:
HPAct = cont.actuators['HPAct'] #a property actuator if the property field is set to HP and you do cont.activate(HPAct) it will automatically change the value of the HP! however, the script will not see this update with own.get('HP') so you need to do HPAct.getValue(), this will work if you have been using this actuator to assign the new adjusted HP value! that means when attacks come in you did your math in a script and output the new HP into the value field of this property actuator with HPAct.setValue(). IGNORE THE DEPRECATION WARNINGS! THEY ARE BOGUS, .value IS NOT A CLEAN REPLACEMENT! clean coding needs full control, by using the deprecated statements we split our read and write operations into two clear alternatives. it saves headaches for instances like when ITEMEquip is "" or blank etc. in those instances .value would function as .getValue() instead of writing "" to the value field.

#now lets define our file read and writes:
SAVE = open('C:/SaveFile.sav', 'w') #this will allow us to write plain text to the file, if you want to write binary data to a file you'd use 'wb'
LOAD = open('C:/SaveFile.sav', 'r') #now you can read information from it, if you need to read binary info use 'rb' actually we are not going to use this, I'm just showing you how it's done for if you need a more complex read system in the future.

#ok what the fuck is this thing below here? it's a function definition, they are handy when you need to separate out different happenings in one script. In this case we will write our save file.

def Pingas():
[tab]if SHIT.positive: #SHIT.positive?, I'm positive that there is definitely some shit going on here!
[tab][tab]SAVE.write(HP+"/n"+MAG+"/n"+MUNAHY+"/n"+BOOMSTICKS+"/n"+ITEMEquip)
[tab][tab]SAVE.close() #this little bastard is important. if you don;t use him on a binary file the file will be corrupt and possibly blank. Always .close() your file after a save or read operation, if you don't you may gt an error next time you attempt to read/write to it "Error: the file is already open", careful not to close before you are actually done with it in that run of the script! if you close() too soon you'll get the error; Error: cannot read/write that file is already closed!

Pingas() # see what I did there? this means that when the script comes to this line and reads it, it will read our code in 'def Pingas()' and do what we told it to. the beauty of our function is that we can call it wherever we like in the script like we would any base level definition.

#end script#



#a base level definition is here
if SHIT.positive:
[tab]print "this is not a base level definition!"#it's level OnE j00 H03! it's only valid for things INSIDE this code bend
[tab]FUCK = print "FUCK"
FUCK #this will not work. evar. it's a level one definition being used at the base level, it will yield a definition error : Error: global name "FUCK" is not defined". and you'll go crazy being like YAS ET IZ!!! but it was defined in a code bend so is only valid for that bend or other levels in that bend such as a level one definition will be seen in level 2 and 3 etc. it's very handy for multi-object code "0n3 5<R1P7 70 R001 7H3M A11!" but we will not be getting into that in this tutorial! maybe a later tutorial.


ok so we now have a save file, how the fuck do we read from it?

when you need to load data from it such as when loading a save slot during the game etc. you will run the following script:

#begin script#
import linecache #woah! wait just a fucking second you didn't do that on the save file writer!. Yes I didn't because it wasn't necessary but is now. there are two ways to read from your file; open().readline(#) where # is the amount of bytes you want it to read into the file, if there are not that many bytes it will return an error. if # is left blank it will read the first line of the document no matter how long, you could viably use this if you had saved your file as a list of values [HP, MAG, MUNAHY, BOOMSTICKS, ITEMEquip] and sometimes it's helpful in games with mass wads of things to save for any one character but for this simple shit, we need to read each line of the document one at a time and .readline() wont read anything but the first line (HP's line) and it's /b/rother .readlines(#) will work-ish but it's a lot more hassle! in .readlines(#) # tells it how many lines to read from the top of the document, meaning it returns more than one line!

linecache.clearcache() # huh? why? because if you don't do that before your read operation each time it will return whatever was read last time, EVEN IF YOU QUIT THE GAME AND RESTART A MILLION TIMES! so clear your cache before you read!

#do the basic shit#
cunt = GameLogic.getCurrentController()
FuckingOWND = cunt.owner

#define you trigger which you are looking for to start the script.
TRIGGER = cont.sensors['pullMyFinger'] #make a sensor named pullMyFinger you'll need it because this will look for that name, if it's not there you'll get an error. before we used '0', that will call the first sensor on the list of sensors on the object, but it's not very good if you have sensor errors where the game glitches the fuck out and forgets to load the sensors when you start the game. So make it a note that you should probably use the name of the sensor instead of it's number on the list.

#define your actuators, different right? at the start we defined properties with own.get() but now we need to set those properties because they have no value!

HPAct = cunt.actuators["HPAct"]
MAGAct = cunt.actuators['MagicAct']
MUNAHYAct = cunt.actuators['GoldAct']
BOOMSTICKSAct = cunt.actuators['ArrowsAct']
ITEMEquipAct = cunt.actuators['ITEMEquipAct']

#each actuator is a property actuator named as above in the [''] their property field is set to their name minus 'Act' and the drop down menu is set to the default 'Assign'.

#define your file j00 dumbbass bass-pole!
HP = linecache.getline('C:/SaveFile.sav', 1) #the first line in the document, you could just use .getlines() and get all the lines as one list then pull entries from that by doing .getlines().split(",")[#] where # is the line you want to retrieve, but that's just bassackwards.
MAG = linecache.getline('C:/SaveFile.sav', 2) #the second line
MUNAHY = linecache.getline('C:/SaveFile.sav', 3)
BOOMSTICKS = linecache.getline('C:/SaveFile.sav', 4)
ITEMEquip = linecache.getline('C:/SaveFile.sav', 5)

#kay, time for teh function!

def MEXICANFOOD():
[tab]if TRIGGER.positive: # :errg you pulled it I knew you couldn't resist!
[tab][tab]#set your values!
[tab][tab]HPAct.setValue("'"+HP+'"') #huh? what the.. ? what are you smoking?. I'm not smoking anything, blender is smoking a [extra characters after expression['#.....']] error. it's actually not an error you will see in the console window like previous errors, this one will appear IN GAME TEXT of the HP property for example. So the thing is no matter what you are trying to set your property to, you MUST set the value of the property actuator as a string STR object of Plain Text normally known in code as "", but if you do "HP" it will write exactly that (HP) to the value field of the property actuator, so you need to feed it the information surrounded by parentheses surrounded by apostrophes, python will automatically see this as "100" if line 1 of the document is 100.
[tab][tab]linecache.clearcache() #HUH? oh right! we just used the cache didn't we? so we need to flush the cache before we can read anything else!
[tab][tab]MAGAct.setValue("'"+MAG+'"')
[tab][tab]linecache.clearcache()
[tab][tab]MUNAHYAct.setValue("'"+MUNAHY+'"')
[tab][tab]linecache.clearcache()
[tab][tab]BOOMSTICKSAct.setValue("'"+BOOMSTICKS+'"')
[tab][tab]linecache.clearcache()
[tab][tab]ITEMEquipAct.setValue("'"+ITEMEquip+'"')
[tab][tab]linecache.clearcache()
[tab][tab]#ACTIVATE TEH LAZER!
[tab][tab]cunt.activate(HPAct)
[tab][tab]cunt.deactivate(HPAct) #Deactivate it to stop future write conflicts!
[tab][tab]cunt.activate(MAGAct)
[tab][tab]cunt.deactivate(MAGAct) #Deactivate it to stop future write conflicts!
[tab][tab]cunt.activate(MUNAHYAct)
[tab][tab]cunt.deactivate(MUNAHYAct) #Deactivate it to stop future write conflicts!
[tab][tab]cunt.activate(BOOMSTICKSAct)
[tab][tab]cunt.deactivate(BOOMSTICKAct) #Deactivate it to stop future write conflicts!
[tab][tab]cunt.activate(ITEMEquipAct)
[tab][tab]cunt.deactivate(ITEMEquipAct) #Deactivate it to stop future write conflicts!
MEXICANFOOD() #congrats you just loaded your game from the file
print "The Game Was Successfully Loaded"

#end script#

that's how you do a document based save file it's probably all you'll need for most games, but for extremely complex games where instead of DEF for all damage sustaining/avoiding calculations, you have light def, dark def, Fire Def, ice def, positive energy def, negative energy def, smashing def, lethal def, explosive def, psychic def, toxic def etc. Then you'll need a database to keep your head in shape otherwise you'll have a shit ton of logic bricks making a massive web of connections and all hell of glitches may break loose. so help yourself by saving all those in one list. another instance where you may need a database is player modifications, so the original attack is [punch, 21 damage, smashing damage type, 1 second animation, 33% chance effect, stun effect, accuracy 25%], but the player has enhanced this entry for their own character, it now needs to show that and a copy of the changes should be saved to a file for good measure so it doesn't get forgotten. Now do that for each attack weapon or power the player has, and you can see why you'll need a database.

I will do a database tutorial in the future.

tutorial over

_________________
mepsipax

Image

got any?

His name is not Robert Paulsen, His name is Gregory Matthew Bruni, he won so hard.

_________________
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.


Mon Aug 01, 2016 12:12 am
Profile E-mail
Level 22
Level 22
User avatar

Cash on hand:
175,593.20
Posts: 2257
Joined: Sat Nov 17, 2012 11:10 am
Location: SR388
Group: Special Access
Post Re: The Project Bane Tutorial Thread
first tutorial up, let me know if you have any questions or such with it.

_________________
mepsipax

Image

got any?

His name is not Robert Paulsen, His name is Gregory Matthew Bruni, he won so hard.

_________________
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.
Click the icon to see the image in fullscreen mode  
1 pcs.


Tue Aug 02, 2016 6:38 am
Profile E-mail
Display posts from previous:  Sort by  
Reply to topic   [ 3 posts ] 
 

Similar topics

 
a thread full of lolz
Forum: ./General Spam
Author: cluelessfurball
Replies: 1
Tutorial: How to block stuff with ad block plus
Forum: ./Tutorials
Author: cluelessfurball
Replies: 2
Top


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Mods Database :: Imprint :: Crawler Feeds :: Reset blocks
Designed by STSoftware for PTF.

Portal XL 5.0 ~ Premod 0.3 phpBB SEO