Computerspellen programmeren (met afbeeldingen)

Inhoudsopgave:

Computerspellen programmeren (met afbeeldingen)
Computerspellen programmeren (met afbeeldingen)
Anonim

Heb je een idee voor een computerspel en wil je het echt maken? Of heb je je ooit afgevraagd hoe computerspellen worden geschreven? Deze wikiHow leert je hoe je drie basiscomputerspellen schrijft in Python. Je hebt een basiskennis van Python en algemene programmeerconcepten nodig om je eerste game te ontwikkelen.

Stappen

Deel 1 van 3: Een op tekst gebaseerd spel maken

5692759 1
5692759 1

Stap 1. Kies een programmeertaal

Alle programmeertalen zijn anders, dus je zult moeten beslissen welke je wilt gebruiken om je spel te schrijven. Elke belangrijke programmeertaal ondersteunt tekstinvoer, tekstuitvoer en if-constructies (de belangrijkste dingen die je nodig hebt voor een eenvoudig op tekst gebaseerd spel), dus verken de opties en beslis welke je het prettigst vindt en toegewijd aan leren. Hier zijn enkele factoren om te overwegen:

  • Waar wordt de taal het meest voor gebruikt?

    Sommige programmeertalen, zoals JavaScript, zijn ontworpen om voor het web te worden gebruikt, terwijl andere, zoals Python, C of C++, zijn ontworpen om computerprogramma's uit te voeren. Streef voor je spel naar een taal met een breder gebruiksbereik, zoals Python, C, C++ of JavaScript.

  • Hoe moeilijk is het om te leren?

    Hoewel het schrijven van een programma na enige oefening in een normale programmeertaal gemakkelijk genoeg zou moeten zijn (d.w.z. niet een specifiek ontworpen om verwarrend te zijn zoals Malbolge), zijn sommige vriendelijker voor beginners dan andere. Java en C vereisen bijvoorbeeld dat je diepere programmeerconcepten begrijpt dan iets als Python, dat bekend staat om zijn meer toegankelijke en ongecompliceerde syntaxis.

  • Waar kan ik het gebruiken?

    Je wilt waarschijnlijk dat mensen op verschillende systemen, zoals Linux, Mac of Windows, allemaal je game kunnen spelen. U moet dus geen taal gebruiken die slechts op enkele systemen wordt ondersteund, zoals Visual Basic, die alleen op Windows wordt ondersteund.

In dit artikel wordt Python gebruikt voor de voorbeelden van een op tekst gebaseerd spel, maar je kunt opzoeken hoe de concepten in een andere programmeertaal worden gedaan.

5692759 2
5692759 2

Stap 2. Maak uw computer gereed

De twee belangrijkste componenten die je nodig hebt, zijn een teksteditor, waarin je je code schrijft, en een compiler, die je zult gebruiken om er een spel van te maken. Als u het voorbeeld in dit artikel wilt volgen, moet u Python installeren en leren hoe u programma's uitvoert. Als je wilt, kun je een IDE (Integraded Desktop Environment) opzetten, die bewerken, compileren en debuggen in één programma combineert. De IDE van Python wordt IDLE genoemd. Maar u kunt ook gewoon elke teksteditor gebruiken die platte tekst ondersteunt, zoals Kladblok voor Windows, TextEdit voor macOS of Vim voor Linux.

5692759 3
5692759 3

Stap 3. Schrijf een code om de speler te begroeten

De speler zal willen weten wat er aan de hand is en wat hij moet doen, dus je moet wat tekst voor hem afdrukken.

  • Dit wordt gedaan met de functie print() in Python. Om het uit te proberen, opent u een nieuw bestand met de extensie.py, voert u de volgende code in, slaat u het op en voert u het uit:

    print("Welkom bij het raadspelletje van getallen!") print("Vul een geheel getal tussen 1 en 1000 in:")

5692759 4
5692759 4

Stap 4. Genereer een willekeurig getal

Laten we een op tekst gebaseerd spel maken waarin de speler wordt gevraagd het juiste getal te raden. Het eerste dat we moeten doen, is aan het begin van het spel een willekeurig getal genereren, zodat de speler niet altijd hetzelfde getal raadt. Omdat het nummer in het hele programma hetzelfde blijft, moet je het willekeurige nummer in een variabele opslaan.

  • Python heeft geen ingebouwde functie voor willekeurige getallen, maar het heeft wel een standaardbibliotheek (dit betekent dat de gebruiker niets extra hoeft te installeren) die dat wel doet. Ga dus naar het begin van je code (vóór de print()-functies) en typ de regel import random.
  • Gebruik de willekeurige functie. Het heet randint(), staat in de willekeurige bibliotheek die je zojuist hebt geïmporteerd, en neemt de minimale en maximale waarde die het getal kan hebben als argument. Ga dus terug naar het einde van je code en voer de volgende regel in:

    rightNum = willekeurig.randint(0, 1000)

5692759 5
5692759 5

Stap 5. Krijg input van de speler

In een game wil de speler iets doen of ergens mee omgaan. In een op tekst gebaseerd spel is dit mogelijk door tekst in te voeren. Nu we een willekeurig getal hebben, moeten onze volgende coderegels de speler vragen om hun beste schatting in te voeren.

  • Aangezien de code die u hebt ingevoerd de instructie afdrukt om een nummer in te voeren voor de speler, zou deze ook het nummer moeten lezen dat ze invoeren. Dit wordt gedaan met input() in Python 3 en raw_input() in Python 2. Je moet schrijven in Python 3, omdat Python 2 binnenkort verouderd zal zijn. Voeg de volgende regel toe aan uw code om de invoer van de speler op te slaan in een variabele met de naam nummer:

    gebruikerNum = invoer()

5692759 6
5692759 6

Stap 6. Verander de input van de speler in een bruikbaar datatype

De speler heeft een nummer ingevoerd, wat nu?

  • Maak van de invoer van de speler een nummer. Dit klinkt misschien verwarrend omdat ze zojuist een nummer hebben ingevoerd. Maar daar is een goede reden voor: Python gaat ervan uit dat alle invoer tekst is, of een "string", zoals dat in het programmeren wordt genoemd. Deze tekst bevat het nummer dat u wilt ontvangen. Python heeft een functie die een string die alleen een getal bevat, omzet naar het getal erin. Type:

    userNum = int(userNum)

5692759 7
5692759 7

Stap 7. Vergelijk het nummer van de speler met het juiste nummer

Zodra de speler zijn nummer heeft ingevoerd, moet je het vergelijken met het nummer dat willekeurig is gegenereerd. Als de nummers niet hetzelfde zijn, kan je spel ervoor zorgen dat de speler een ander nummer probeert. Als de nummers overeenkomen, mag je de speler vertellen dat hij het goed heeft geraden en het programma afsluiten. Dit gebeurt met de volgende code:

while userNum != rightNum: userNum = int(input())

5692759 8
5692759 8

Stap 8. Geef de speler feedback

Terwijl je hun invoer al hebt verwerkt, ziet de speler dit niet. U moet de resultaten daadwerkelijk naar de speler afdrukken, zodat ze begrijpen wat er gebeurt.

  • Natuurlijk kun je de speler gewoon vertellen of zijn nummer goed of fout is. Maar met die benadering zou de speler in het ergste geval misschien 1000 keer moeten raden, wat erg saai zou zijn.
  • Vertel de speler dus of zijn of haar aantal te klein of te groot is. Dit zal hun aantal gissingen aanzienlijk verminderen. Als de speler bijvoorbeeld eerst 500 raadt en het spel antwoordt "Te groot. Probeer het opnieuw", zijn er slechts 500 mogelijke getallen in plaats van 1000. Dit wordt gedaan met if-constructies, dus vervang de print("Wrong. Probeer het opnieuw.") met één.
  • Houd er rekening mee dat controleren of twee getallen hetzelfde zijn, wordt gedaan met ==, niet met =. = wijst de waarde rechts ervan toe aan de variabele links ervan!
  • if userNum < rightNum: print("Te klein. Probeer het opnieuw:") if userNum > rightNum: print("Te groot. Probeer het opnieuw:")

5692759 9
5692759 9

Stap 9. Test je code

Als programmeur moet u er zeker van zijn dat uw code werkt voordat u deze als voltooid beschouwt.

  • Zorg er bij het programmeren in python voor dat de inspringingen correct zijn. Uw code zou er als volgt uit moeten zien:

    import random print("Welkom bij het nummer raadspel!") print("Voer een geheel getal in tussen 1 en 1000:") rightNum = random.randint(0, 1000) userNum = input() userNum = int(userNum) while userNum != rightNum: if userNum < rightNum: print("Te klein. Probeer het opnieuw:") if userNum > rightNum: print("Te groot. Probeer het opnieuw:") userNum = int(input()) print("Je raadt het al correct.")

5692759 10
5692759 10

Stap 10. Valideer de invoer

De speler zou je spel niet moeten kunnen breken door simpelweg het verkeerde in te voeren. "De invoer valideren" betekent ervoor zorgen dat de speler het juiste item heeft ingevoerd voordat het wordt verwerkt.

  • Open het spel opnieuw en probeer iets in te voeren dat geen nummer is. Het spel wordt afgesloten met een ValueError. Om dit te voorkomen, kunt u een manier implementeren om te controleren of de invoer een getal was.
  • Definieer een functie. Aangezien het valideren van de invoer vrij lang duurt en u het meerdere keren moet doen, moet u een functie definiëren. Er zijn geen argumenten voor nodig en er wordt een getal geretourneerd. Schrijf eerst def numInput(): bovenaan je code, direct onder de import random.
  • Ontvang één keer de input van de speler. Gebruik de functie input() en wijs het resultaat toe aan de variabele inp.
  • Als de invoer van de speler geen nummer is, vraag hem dan om een nummer in te voeren. Om te controleren of een tekenreeks een getal is, gebruikt u de isdigit()-functies, die alleen een geheel getal toestaan, dus u hoeft dat niet apart te controleren.
  • Als de invoer een getal is, converteer het dan van tekenreeks naar getal en retourneer het resultaat. Gebruik de functie int() om de tekenreeks naar een geheel getal te converteren. Dit maakt de conversie in de hoofdcode overbodig en u moet deze daar verwijderen.
  • Vervang alle oproepen naar input() in de hoofdcode door oproepen naar numInput().
  • De code van de functie numInput() ziet er als volgt uit:
  • def numInput(): inp = input() terwijl niet inp.isdigit(): print("U werd verteld om een geheel getal in te voeren! Voer een geheel getal in:") inp = input() return int(inp)

5692759 11
5692759 11

Stap 11. Test het spel opnieuw

Voer expres de verkeerde dingen in om te zien wat er gebeurt en corrigeer eventuele fouten zodra ze zich voordoen.

Probeer wat tekst in te voeren wanneer het programma u om een nummer vraagt. Nu, in plaats van af te sluiten met een foutmelding, zal het programma u opnieuw om een nummer vragen

5692759 12
5692759 12

Stap 12. Stel voor om het spel opnieuw te starten als het klaar is

Op deze manier kan de speler je spel langer spelen zonder het steeds opnieuw te moeten opstarten.

  • Zet alle code behalve de import en de functiedefinitie in een while-loop. Stel True in als de voorwaarde: dit zal altijd waar zijn, dus de lus zal voor altijd doorgaan.
  • Vraag de speler of ze nog een keer willen spelen nadat ze het nummer correct hebben geraden. Gebruik de print() functie.
  • Als ze "Nee" antwoorden, breek dan uit de blik. Als ze iets anders antwoorden, ga dan verder. Het doorbreken van een lus gebeurt met de break-statement.
  • Verplaats het "Welkom bij het raadspelletje" buiten de while-lus. De speler wil waarschijnlijk niet elke keer dat hij het spel speelt verwelkomd worden. Verplaats de instructie print ("Welkom bij het spel voor het raden van getallen!" boven de while True:, zodat deze maar één keer wordt afgedrukt, wanneer de gebruiker het eerste spel start.
5692759 13
5692759 13

Stap 13. Test het spel

Elke keer dat je een nieuwe functie implementeert, moet je je game testen.

  • Zorg ervoor dat u zowel "Ja" als "Nee" minstens één keer beantwoordt om er zeker van te zijn dat beide opties werken. Hier is hoe uw code eruit zou moeten zien:

    import random def numInput(): inp = input() while not inp.isdigit(): print("U werd verteld om een geheel getal in te voeren! Voer een geheel getal in:") inp = input() return int(inp) print ("Welkom bij het spel voor het raden van getallen!") while True: print("Voer een geheel getal in tussen 1 en 1000:") rightNum = random.randint(0, 1000) userNum = numInput() while userNum != rightNum: if userNum < rightNum: print("Te klein. Probeer het opnieuw:") if userNum > rightNum: print("Te groot. Probeer het opnieuw:") userNum = numInput() print("Je hebt het goed geraden.") print("Heb je wil je nog een keer spelen? Voer No in om te stoppen.") if input() == "No": break

5692759 14
5692759 14

Stap 14. Schrijf andere op tekst gebaseerde spellen

Wat dacht je ervan om vervolgens een tekstavontuur te schrijven? Of een quizspel? Wees creatief.

Tip: Het is soms handig om in de documentatie te kijken als je niet zeker weet hoe iets wordt gedaan of hoe een functie wordt gebruikt. De Python 3-documentatie is te vinden op https://docs.python.org/3/. Soms levert het zoeken naar wat u maar wilt op internet ook goede resultaten op.

Deel 2 van 3: Een spel maken met 2D-graphics

5692759 15
5692759 15

Stap 1. Kies een grafische bibliotheek

Het maken van afbeeldingen is erg ingewikkeld en de meeste programmeertalen (inclusief Python, C++, C, JavaScript) bieden slechts minimale of zelfs geen ondersteuning voor afbeeldingen in de kern of de standaardbibliotheken. Je zult dus een externe bibliotheek moeten gebruiken om afbeeldingen te kunnen maken, bijvoorbeeld Pygame voor Python.

Zelfs met een grafische bibliotheek moet u zich zorgen maken over zaken als hoe u een menu moet weergeven, hoe u kunt controleren waarop de speler heeft geklikt, hoe de tegels moeten worden weergegeven, enzovoort. Als je je liever concentreert op het ontwikkelen van het eigenlijke spel, kun je een game-enginebibliotheek zoals Unity gebruiken, die deze dingen gemakkelijk implementeert

In dit artikel wordt Python met Cocos2D gebruikt om te laten zien hoe je een eenvoudige 2D-platformgame maakt. Sommige van de genoemde concepten bestaan mogelijk niet in andere game-engines. Raadpleeg hun documentatie voor meer informatie.

5692759 16
5692759 16

Stap 2. Installeer de grafische bibliotheek die u hebt gekozen

Cocos2D voor Python is eenvoudig te installeren. Je kunt het krijgen van https://python.cocos2d.org/index.html, of door sudo pip3 install cocos2d uit te voeren als je Linux gebruikt.

5692759 17
5692759 17

Stap 3. Maak een nieuwe map voor je game en media

Je gebruikt dingen als afbeeldingen en geluiden in je spel. Bewaar deze dingen in dezelfde map als het programma. Deze map mag niets anders bevatten, zodat je gemakkelijk kunt zien welke middelen je in het spel hebt.

5692759 18
5692759 18

Stap 4. Maak een nieuw codebestand aan in de nieuwe map

Noem het main, met de bestandsextensie voor uw programmeertaal. Als je een groot en complex programma schrijft waarbij het logisch is om meerdere programmabestanden te hebben, dan zal dit je laten zien wat het hoofdbestand is.

In dit voorbeeld maken we een bestand met de naam main.py dat al onze code zal bevatten

5692759 19
5692759 19

Stap 5. Maak het spelvenster aan

Dit is de basisvoorwaarde voor een game met graphics.

  • Importeer de benodigde cocos2d sub-modules: cocos.director, cocos.scene en cocos.layer. Dit doet u met from subModuleName import *, waarbij sub-Module name de submodule is die u wilt importeren. Het verschil tussen van … import * en import … is dat je de modulenaam niet voor alles hoeft te zetten wat je uit die module met de vorige gebruikt.
  • Definieer een subklasse MainMenuBgr van de ColorLayer. Dit betekent in feite dat elke achtergrond van het hoofdmenu die u maakt, zich zal gedragen als een kleurlaag met enkele wijzigingen die u aanbrengt.
  • Start de Cocos Director. Je krijgt dan een nieuw venster. Als u geen bijschrift instelt, heeft het venster hetzelfde bijschrift als de bestandsnaam (main.py), wat er niet professioneel uitziet. Sta toe dat de grootte van het venster wordt gewijzigd met door de grootte in te stellen op True.
  • Definieer een functie showMainMenu. U moet de code voor het tonen van het hoofdmenu in een functie plaatsen, omdat u dan gemakkelijk terug kunt keren naar het hoofdmenu door de functie opnieuw aan te roepen.
  • Maak een scène. De scène bestaat voorlopig uit één laag, wat een object is van de MainMenuBgr-klasse die u hebt gedefinieerd.
  • Voer deze scène uit in het venster.
  • from cocos.director import * from cocos.scene import * from cocos.layer import * class MainMenuBgr(ColorLayer): def _init_(self): super(MainMenu, self)._init_(0, 200, 255, 255) def showMainMenu(): menuSc = Scene(MainMenuBgr()) director.run(menuSc) director.init(caption="IcyPlat - een eenvoudige platformgame", resizable=True) showMainMenu()

5692759 20
5692759 20

Stap 6. Voeg een hoofdmenu toe aan het venster

Naast het eigenlijke spel, moet je een menu toevoegen dat de speler kan gebruiken om het venster te sluiten, naast andere elementen die je later kunt toevoegen.

  • Importeer cocos.menu (opnieuw met de instructie from) en pyglet.app (dit keer met import).
  • Definieer MainMenu als een subklasse van Menu.
  • Stel de uitlijning van het hoofdmenu in. U moet de verticale en horizontale uitlijning apart instellen.
  • Maak een lijst met menu-items en voeg ze toe aan het menu. Je zou op zijn minst de menu-items "Start Game" en "Quit" moeten hebben. Elk menu-item moet tussen haakjes worden geplaatst. Elk item moet een label en een callback-functie hebben die bepaalt wat er gebeurt als de speler erop klikt. Gebruik voor het item "Game starten" de functie startGame (je schrijft het binnenkort), gebruik voor het item "Sluiten" "pyglet.app.exit" (bestaat al). Maak het eigenlijke menu door self.create_menu(menuItems) aan te roepen.
  • Definieer startGame(). Zet gewoon pass in de definitie voor nu, je zult dat vervangen wanneer je het eigenlijke spel schrijft.
  • Ga naar de plaats in je code waar je de menuSc-scène hebt gemaakt en voeg er een MainMenu-object aan toe.
  • Uw volledige code zou er nu als volgt uit moeten zien:

    from cocos.director import * from cocos.menu import * from cocos.scene import * from cocos.layer import * import pyglet.app class MainMenuBgr(ColorLayer): def _init_(self): super(MainMenuBgr, self)._init_(0, 200, 255, 255) class MainMenu(Menu): def _init_(self): super(MainMenu, self)._init_("") self.menu_valign = CENTER self.menu_halign = CENTER menuItems = [(MenuItem("Start Game) ", startGame)), (MenuItem("Quit", pyglet.app.exit))] self.create_menu(menuItems) def startGame(): pass def showMainMenu(): menuSc = Scene(MainMenuBgr()) menuSc.add(MainMenu()) director.run(menuSc) director.init(caption="IcyPlat - een eenvoudige platformgame", resizable=True) showMainMenu()

5692759 21
5692759 21

Stap 7. Test je code

Test de code vroeg, terwijl het nog steeds kort en relatief eenvoudig is. Dan kunt u eventuele fouten in de basisstructuur identificeren en corrigeren voordat het te ingewikkeld wordt.

De code uit de instructies zou een venster moeten openen met de titel "IcyPlat - een eenvoudige platformgame." De achtergrond is lichtblauw en u kunt het formaat van het venster wijzigen. Als je in het menu op "Game starten" klikt, zou er (nog) niets moeten gebeuren. Wanneer u op "Afsluiten" klikt, wordt het venster gesloten

5692759 22
5692759 22

Stap 8. Maak een sprite

Een sprite is een 'spelobject' of een 2-dimensionaal beeld. Sprites kunnen in-game-objecten, pictogrammen, achtergronddecoraties, personages en al het andere zijn dat je kunt vertegenwoordigen met een afbeelding in het spel. We beginnen met het maken van een sprite voor een personage waarmee de speler kan communiceren.

  • Importeer de cocos.sprite submodule met de from-import-expression.
  • Zoek een afbeelding om de sprite weer te geven. Je kunt een sprite niet weergeven als je er geen afbeelding voor hebt. Je kunt er een tekenen, of je kunt er een van internet halen (pas echter op voor de licenties als je van plan bent je spel te publiceren). Ga voor dit voorbeeld naar https://opengameart.org/content/tux-classic-hero-style en sla de PNG-afbeelding van rennende pinguïns op je computer op. Knip dan een van de rennende pinguïns uit, want je hebt er voorlopig maar één nodig.
  • Maak een laag als een nieuw object van de klasse ScrollableLayer. Maak vervolgens de sprite als een Sprite-object en stel de positie in op (8, 250). Ter referentie: het punt (0, 0) bevindt zich in de linkerbenedenhoek. Dit is vrij hoog, maar het zorgt er wel voor dat de pinguïn niet vast komt te zitten in het ijs.
  • Voeg de sprite toe aan de laag van de sprite.
  • Maak een nieuwe scène uit de laag van de sprite en voer deze uit.
  • def startGame(): figLayer = ScrollableLayer() fig = Sprite('pingu.png') fig.position = (75, 100) figLayer.add(fig) # gameSc = Scene(figLayer) director.run(gameSc)

  • Voer de code uit. Je zou een kleine pinguïnfiguur (of wat je ook hebt getekend) op een zwarte achtergrond moeten zien nadat je hebt geklikt Start het spel.
5692759 23
5692759 23

Stap 9. Bedenk je landschap

In de meeste games moeten je sprites niet zomaar in de leegte zweven. Ze zouden eigenlijk op een oppervlak moeten staan, met iets om hen heen. In 2D-spellen wordt dit vaak gedaan met een tegelset en een tegelkaart. De tegelset zegt in feite wat voor soort oppervlaktevierkanten en achtergrondvierkanten er zijn en hoe ze eruit zien.

  • Maak een tegelset. De tegelset voor dit spel zal heel eenvoudig zijn: één tegel voor ijs en één tegel voor lucht. De ijstegel die in dit voorbeeld wordt gebruikt, komt hier vandaan, onder CC-BY-SA 3.0.
  • Maak een tegelsetafbeelding. Dat is een afbeelding van alle tegels, die allemaal even groot moeten zijn (bewerk ze als dat niet het geval is) en het formaat hebben dat je in het spel wilt zien, naast elkaar. Sla je afbeelding op als icyTiles.png.
  • Maak de beschrijving van de tegelset. Dat is een XML-bestand. Het XML-bestand bevat informatie over hoe groot de tegels in de tegelsetafbeelding zijn, welke afbeelding u moet gebruiken en waar u welke tegel daar kunt vinden. Maak een XML-bestand met de naam icyTiles.xml met de onderstaande code:

         
    
5692759 24
5692759 24

Stap 10. Maak een tegelkaart voor je landschap

Een tegelkaart is een kaart die bepaalt welke tegel zich op welke positie in je level bevindt. In het voorbeeld moet u een functie definiëren om tegelkaarten te genereren, omdat het handmatig ontwerpen van tegelkaarten erg vervelend is. Een meer geavanceerd spel heeft meestal een soort niveau-editor, maar om vertrouwd te raken met de ontwikkeling van 2D-games, kan een algoritme voldoende niveaus bieden.

  • Ontdek hoeveel rijen en kolommen er nodig zijn. Deel hiervoor zowel horizontaal (kolommen) als verticaal (rijen) de schermgrootte door de tegelgrootte. Rond het getal naar boven af; daar heb je een functie van de wiskundemodule voor nodig, dus voeg van math import ceil toe aan de imports bovenaan je code.
  • Open een bestand om te schrijven. Hiermee wordt alle eerdere inhoud van het bestand gewist, dus kies een naam die nog geen bestand in de map heeft, zoals levelMap.xml.
  • Schrijf de openingstags in het bestand.
  • Genereer een tegelkaart volgens het algoritme. Je gebruikt die in de onderstaande code, of je kunt er zelf een bedenken. Zorg ervoor dat je de randint-functie uit de module random importeert: het is vereist om de onderstaande code te laten werken, en wat je ook bedenkt, er zijn waarschijnlijk ook willekeurige gehele getallen nodig. Zorg er ook voor dat je hemeltegels en ijstegels in verschillende lagen legt: ijs is vast, lucht niet.
  • Schrijf de afsluitende tags in het bestand en sluit het bestand.
  • def GenereerTilemap(): colAmount = ceil(800/16)*3 # (schermbreedte/tegelgrootte) * 3 rowAmount = ceil(600/16) # schermhoogte/tegelgrootte tileFile = open("levelMap.xml", " w") tileFile.write('\n\n\n') iceHeight = randint(1, 10) for i in range(0, colAmount): tileFile.write('') makeHole = False if randint(0, 50) == 10 en i != 0: # laat geen gaten toe op het spawnpoint makeHole = True voor j in range(0, rowAmount): if makeHole: tileFile.write('\n') else: if j <= iceHeight: tileFile.write('\n') else: tileFile.write('\n') iceHeight = randint(iceHeight-5, iceHeight+5) als iceHeight < 0: # beperk dat tegels te laag worden iceHeight = randint(1, 5) if iceHeight > rowAmount: # beperk dat tegels te hoog worden iceHeight = randint(int(rowAmount/2)-5, int(rowAmount/2)+5) tileFile.write('\n') tileFile.write ('\n\n') voor i in range(0, colAmount): tileFile.write('') voor j in range(0, rowAmount): tileFile.write('\n') tileFile.write('\ n') tileFile.write('\n\n') tileFile.close()

5692759 25
5692759 25

Stap 11. Geef de tegelkaart weer

Importeer alles van cocos.tiles en ga daarvoor naar de startGame-functie.

  • Genereer aan het begin van je startGame-functie een tegelkaart met de functie die je daarvoor hebt gedefinieerd.
  • Maak een nieuwe scrollmanager. Doe dit direct onder de lijn waar je de sprite aan zijn laag toevoegt.
  • Maak een nieuwe laag die de tegels bevat, die zal worden geladen vanaf de levelMap.xml-tegelkaart die door uw generatorTilemap-functie is gegenereerd.
  • Voeg de niet-vaste laag, de vaste laag en de sprite-laag toe aan de scrollmanager, precies in deze volgorde. U kunt desgewenst een z-positie toevoegen.
  • In plaats van de scène vanuit de sprite-laag te maken, maakt u deze vanuit de scrollmanager.
  • Je startGame-functie zou er nu als volgt uit moeten zien:

    def startGame(): genereerTilemap() # fig = Sprite('pingu.png') fig.position = (8, 500) figLayer = ScrollableLayer() figLayer.add(fig) # tileLayer = load('levelMap.xml') solidTiles = tileLayer['solid'] nsoliTiles = tileLayer['not_solid'] # scrMang = ScrollingManager() scrMang.add(nsoliTiles, z=-1) scrMang.add(solidTiles, z=0) scrMang.add(figLayer, z =1) # gameSc = Scene(scrMang) director.run(gameSc)

5692759 26
5692759 26

Stap 12. Test je code

U moet uw code vaak testen om er zeker van te zijn dat de nieuwe functies die u hebt geïmplementeerd echt werken.

De code in het voorbeeld zou nu een ijzig landschap achter de pinguïn moeten laten zien. Als de pinguïn eruitziet alsof hij ver boven het ijs zweeft, heb je niets verkeerd gedaan en wordt het in de volgende stap opgelost

5692759 27
5692759 27

Stap 13. Voeg de bedieningselementen toe

De speler heeft veel meer manieren om met het programma te communiceren in een 2D-spel dan in een op tekst gebaseerd spel. Een veel voorkomende is het verplaatsen van hun figuur wanneer de juiste toets wordt ingedrukt.

  • Importeer alles van cocos.mapcolliders en van cocos.actions. Importeer ook sleutel uit pyglet.window.
  • "Declareer" enkele globale variabelen. Globale variabelen worden gedeeld tussen functies. Je kunt variabelen niet echt declareren in Python, maar je moet zeggen dat er een globale variabele in de hoofdcode bestaat voordat je deze gebruikt. U kunt 0 als waarde toewijzen omdat een functie er later voor zorgt dat de juiste waarde wordt toegewezen. Dus voeg onder de importexpressies toe:

    # globale variabelen "declareren" toetsenbord = 0 scrMang = 0

  • Pas je startGame-functie aan:

    • Stel dat u het toetsenbord met globale variabelen en scrMang gebruikt. Doe dit door globaal toetsenbord, scrMang bovenaan de functie te schrijven.
    • Laat het venster luisteren naar toetsenbordgebeurtenissen.
    • Vertel de figuur om te handelen op basis van een PlatformerController. Je zult die PlatformerController binnenkort implementeren.
    • Maak een kaartversneller om botsingen tussen de massieve tegels en de figuur aan te pakken.

    def startGame(): globaal toetsenbord, scrMang genereerTilemap() # fig = Sprite('pingu.png') fig.position = (8, 250) figLayer = ScrollableLayer() figLayer.add(fig) # tileLayer = load('levelMap XML) solidTiles = tileLayer ['vaste '] = nsoliTiles tileLayer [' not_solid'] = # toetsenbord key. KeyStateHandler () director.window.push_handlers (keyboard) # fig.do (PlatformerController ()) = mapcollider RectMapCollider (velocity_on_bump ='slide') fig.collision_handler = make_collision_handler(mapcollider, solidTiles) # scrMang = ScrollingManager() scrMang.add(nsoliTiles, z=-1) scrMang.add(solidTiles, z=0) scrMang.add(figLayer, z= 1) # gameSc = Scene(scrMang) director.run(gameSc)

  • Maak een platformgame-controller. Dit is wat de figuur zal verplaatsen volgens uw toetsaanslagen.

    • Definieer de platformer-controller als een subklasse van Action.
    • Definieer de bewegingssnelheid, de springsnelheid en de zwaartekracht.
    • Definieer de startfunctie. Deze functie wordt één keer aangeroepen, wanneer de platformer-controller is verbonden met de figuur. Het moet zijn snelheid zowel in x- als in y-richting op 0 instellen.
    • Definieer de stapfunctie. Het wordt herhaald terwijl de scène draait.
    • Vertel de stapfunctie om het toetsenbord met globale variabelen en scrMang te gebruiken.
    • Verkrijg en verander de snelheid. Sla de x- en de y-snelheid op in afzonderlijke variabelen. Stel de x-snelheid in op 1 of -1 (afhankelijk van of de linker- of rechtertoets is ingedrukt) vermenigvuldigd met de bewegingssnelheid. Voeg de zwaartekracht toe aan de y-snelheid. Vermenigvuldig het met downtime, zodat het op langzamere apparaten op dezelfde manier werkt. Als de spatietoets is ingedrukt en de figuur staat op de grond, spring dan door y snelheid te veranderen in springsnelheid.
    • Bereken naar waar de figuur moet bewegen. Laat de aanrijdingshandler vervolgens die positie aanpassen als deze zich in een massieve tegel bevindt. Verplaats ten slotte de figuur naar de nieuwe aangepaste positie.
    • Stel de focus van de scrollmanager in op de figuur. Hierdoor beweegt de camera op een redelijke manier als de figuur beweegt.

    class PlatformerController(Action): globaal toetsenbord, scrMang on_ground = True MOVE_SPEED = 300 JUMP_SPEED = 500 GRAVITY = -1200 def start(self): self.target.velocity = (0, 0) def step (self, dt): globaal toetsenbord, scroller als dt > 0.1: # niets doen tijdens downtime naar grote return vx, vy = self.target.velocity vx = (keyboard[key. RIGHT] - keyboard[key. LEFT]) * self. MOVE_SPEED vy + = self. GRAVITY * dt if self.on_ground en toetsenbord[key. SPACE]: vy = self. JUMP_SPEED dx = vx * dt dy = vy * dt last = self.target.get_rect() new = last.copy() new.x += dx new.y += dy self.target.velocity = self.target.collision_handler(last, new, vx, vy) self.on_ground = (new.y == laatste.y) self.target.position = nieuw.center scrMang.set_focus(*nieuw.center)

5692759 28
5692759 28

Stap 14. Test je code

Als je het voorbeeld hebt gevolgd, zou je nu in staat moeten zijn om de pinguïn te verplaatsen met de pijltjestoetsen en te springen door op de spatiebalk te drukken. Ook zou de pinguïn nu naar beneden moeten vallen in plaats van over de grond te zweven.

5692759 29
5692759 29

Stap 15. Creëer een einde voor het spel

Zelfs de spellen die eindeloos kunnen doorgaan, moeten de mogelijkheid hebben om te verliezen. Aangezien het niveau dat je in het voorbeeld met een functie hebt gemaakt een einde heeft, moet je het ook mogelijk maken om te winnen door aan dat einde te komen. Anders zou de speler daar alleen maar rondspringen op de ijsblokken, wat saai zou worden.

  • In de platformer-controller, na de focusset, krijg je de x- en y-positie van de figuur. Als de y-positie kleiner is dan 0, roep dan de functie finishGame() aan (je schrijft het later) met "Game Over" als argument. Als de x-positie groter is dan de grootte van het scherm vermenigvuldigd met 3 (je had dat eerder als niveaugrootte ingesteld).

    posX, posY = self.target.position indien posY < 0: finishGame("Game Over") return indien posX > 800*3: # level size finishGame("Level Completed") return

  • Definieer een klasse finishMenu. Het zou moeten zijn zoals de hoofdmenuklasse die je eerder hebt gedefinieerd, maar in plaats van een lege tekenreeks als titel te hebben, zou het een variabele tekst moeten gebruiken die de functie _init_ als argument neemt. De menu-items zouden nu het label "Probeer opnieuw" en "Afsluiten" moeten hebben, maar de functies die ze oproepen blijven hetzelfde.

    class FinishMenu(Menu): def _init_(self, text): super(FinishMenu, self)._init_(text) self.menu_valign = CENTER self.menu_halign = CENTER menuItems = [(MenuItem("Probeer opnieuw", startGame)), (MenuItem("Sluiten", pyglet.app.exit))] self.create_menu(menuItems)

  • Definieer de functie finishGame(). Het zou tekst als argument moeten nemen. Het zou een scène moeten maken van de achtergrond van het hoofdmenu, een FinishMenu met het tekstargument dat aan dit menu wordt doorgegeven. Dan zou het deze scène moeten draaien.

    def finishGame(tekst): menuSc = Scene(HoofdmenuBgr()) menuSc.add(FinishMenu(tekst)) director.run(menuSc)

5692759 30
5692759 30

Stap 16. Credits toevoegen

Hier krijg je de eer voor je geweldige code, en geef je ook de eer aan iemand anders die je onderweg heeft geholpen. Als je een afbeelding van een andere website hebt gebruikt (met toestemming), zorg er dan voor dat je die afbeelding toeschrijft aan de maker ervan.

  • Maak een bestand KREDIETEN aan en vul daar al je tegoeden in, zoals dit:

    Pinguïn: Kelvin Shadewing, onder CC0 IJsblok: Michał Banas digit1024 op opengameart.org onder CC-BY-SA 3.0

  • Ga terug naar je Python-code en importeer Label van cocos.text.
  • Definieer een subklasse Credits of Layer. In zijn _init_-functie, lees het CREDITS-bestand en maak een tekstlabel op de juiste positie van elke regel erin.

    class Credits(Laag): def _init_(self): super(Credits, self)._init_() credFile = open("CREDITS", "r") creds = credFile.read() creds = creds.split("\n ") for i in range(0, len(creds)): credLabel = Label(creds, font_size=32, anchor_x="left", anchor_y="top") credLabel.position = 25, 500-(i +1)*40 zelf.add(credLabel)

  • Ga naar je hoofdmenuklasse en voeg een menu-item toe met het label "Credits" dat de functie showCredits aanroept wanneer erop wordt geklikt.
  • Definieer een subklasse BackToMainMenuButton van Menu. Maak dit een menu met één item, genaamd "Terug", dat de showMainMenu-functie aanroept. Dit "menu", dat meer op een knop lijkt, moet verticaal naar beneden en horizontaal naar boven worden uitgelijnd.

    class BackToMainMenuButton(Menu): def _init_(self): super(BackToMainMenuButton, self)._init_("") self.menu_valign = BOTTOM self.menu_halign = LEFT menuItems = [(MenuItem("Back", showMainMenu))] self. create_menu(menuItems)

  • Definieer de functie showCredits. Het zou een scène moeten maken van een MainMenuBgr-laag en een Credits-laag en die scène moeten uitvoeren.

    def showCredits(): credSc = Scene(MainMenuBgr()) credSc.add(Credits()) credSc.add(BackToMainMenuButton()) director.run(credSc)

5692759 31
5692759 31

Stap 17. Controleer je code

Als je denkt dat je klaar bent met je code, moet je alles nog een keer bekijken. Dit kan u helpen op te merken of iets kan worden geoptimaliseerd, of dat er enkele onnodige regels zijn die u bent vergeten te verwijderen. Als je het voorbeeld hebt gevolgd, zou je hele code er nu als volgt uit moeten zien:

    uit cocos.director import * uit cocos.menu import * uit cocos.scene import * uit cocos.layer import * uit cocos.sprite import * uit cocos.tiles import * uit cocos.mapcolliders import * uit cocos.actions import * uit cocos.text import Label import pyglet.app van pyglet.window importsleutel van wiskunde import ceil van willekeurige import randint # "declaring" globale variabelen keyboard = 0 scrMang = 0 class MainMenuBgr(ColorLayer): def _init_(self): super(MainMenuBgr, self)._init_(0, 200, 255, 255) class MainMenu(Menu): def _init_(self): super(Hoofdmenu, zelf)._init_("") self.menu_valign = CENTER self.menu_halign = CENTER menuItems = [(MenuItem("Start Game", startGame)), (MenuItem("Credits", showCredits)), (MenuItem("Quit", pyglet.app.exit))] self.create_menu(menuItems) class Credits(Layer): def _init_(self): super(Credits, self)._init_() credFile = open("CREDITS", "r") creds = credFile.read() creds = creds.split("\n") for i binnen bereik (0, len(creds)): credLabel = Label(creds, font_size=32, anchor_x="left", anchor_y="top") credLabel.position = 25, 500-(i+1)*40 self.add(credLabel) class BackToMainMenuButton(Menu): def _init_(self): super (BackToMainMenuButton, self)._init_("") self.menu_valign = BOTTOM self.menu_halign = LEFT menuItems = [(MenuItem("Back", showMainMenu))] self.create_menu(menuItems) class FinishMenu(Menu): def _init_(zelf, tekst): super(FinishMenu, zelf)._init_(tekst) self.menu_valign = CENTER self.menu_halign = CENTER menuItems = [(MenuItem("Probeer opnieuw", startGame)), (MenuItem("Quit", pyglet. app.exit))] self.create_menu(menuItems) class PlatformerController(Action): globaal toetsenbord, scrMang on_ground = True MOVE_SPEED = 300 JUMP_SPEED = 500 GRAVITY = -1200 def start(self): self.target.velocity = (0, 0) def step(self, dt): globaal toetsenbord, scroller indien dt > 0.1: # niets doen terwijl de downtime te groot is return vx, vy = self.target.velocity vx = (keyboard[key. RIGHT] - keyboard [key. LEFT]) * self. MOVE_SPEED vy += self. GRAVITY * dt if self.on _ground en toetsenbord[key. SPACE]: vy = self. JUMP_SPEED dx = vx * dt dy = vy * dt last = self.target.get_rect() new = last.copy() new.x += dx new.y + = dy self.target.velocity = self.target.collision_handler(last, new, vx, vy) self.on_ground = (new.y == last.y) self.target.position = new.center scrMang.set_focus(* new.center) posX, posY = self.target.position indien posY < 0: finishGame("Game Over") return indien posX > 800*3: # level size finishGame("Level Completed") return def finishGame(text): menuSc = Scene(HoofdmenuBgr()) menuSc.add(FinishMenu(tekst)) director.run(menuSc) def showCredits(): credSc = Scene(MainMenuBgr()) credSc.add(Credits()) credSc.add(BackToMainMenuButton()) director.run(credSc) def generationTilemap(): colAmount = ceil(800/16)*3 # (schermbreedte/tegelgrootte) * 3 rowAmount = ceil(600/16) # schermhoogte/tegelgrootte tileFile = open ("levelMap.xml", "w") tileFile.write('\n\n\n') iceHeight = randint(1, 10) for i in range(0, colAmount): tileFile.write('') makeHole = Onwaar indien rand int(0, 50) == 10 en i != 0: # laat geen gaten toe op het spawnpoint makeHole = True voor j in range(0, rowAmount): if makeHole: tileFile.write('\n') else: if j <= iceHeight: tileFile.write('\n') else: tileFile.write('\n') iceHeight = randint(iceHeight-5, iceHeight+5) if iceHeight < 0: # beperk dat tegels meegaan laag iceHeight = randint(1, 5) if iceHeight > rowAmount: # beperk dat tegels te hoog worden iceHeight = randint(int(rowAmount/2)-5, int(rowAmount/2)+5) tileFile.write('\n ') tileFile.write('\n\n') for i in range(0, colAmount): tileFile.write('') for j in range(0, rowAmount): tileFile.write('\n') tileFile.write('\n') tileFile.write('\n\n') tileFile.close() def startGame(): globaal toetsenbord, scrMang GenereerTilemap() # fig = Sprite('pingu.png') fig.position = (8, 250) figLayer = ScrollableLayer() figLayer.add(fig) # tileLayer = load('levelMap.xml') solidTiles = tileLayer['solid'] nsoliTiles = tileLayer['not_solid'] # keyboard = key. KeyStateHandler () director.window.push_handlers(keybo ard) # fig.do(PlatformerController()) mapcollider = RectMapCollider(velocity_on_bump='slide') fig.collision_handler = make_collision_handler(mapcollider, solidTiles) # scrMang = ScrollingManager() scrMang.add,=nsoliTiles add(solidTiles, z=0) scrMang.add(figLayer, z=1) # gameSc = Scene(scrMang) director.run(gameSc) def showMainMenu(): menuSc = Scene(HoofdmenuBgr()) menuSc.add(Hoofdmenu()) director.run(menuSc) window = director.init(caption="IcyPlat - een eenvoudige platformgame", resizable=True) showMainMenu()

  • Dat zijn in totaal 168 regels, en 152 regels als je alleen de code meetelt. Dit lijkt veel, maar voor zo'n complex spel is dit eigenlijk een klein bedrag.
5692759 32
5692759 32

Stap 18. Klaar

Test nu het spel. Als je iets programmeert, moet je altijd controleren of het werkt als je iets nieuws hebt geïmplementeerd. Ook wil je misschien het spel spelen dat je al een tijdje hebt geschreven.

Deel 3 van 3: Een game publiceren

5692759 52
5692759 52

Stap 1. Schrijf de afhankelijkheden op

Iedereen die een andere computer gebruikt, heeft niet dezelfde software en bibliotheken als u geïnstalleerd. Je moet er dus voor zorgen dat iedereen die je spel installeert precies weet wat ze nodig hebben om het uit te voeren. Je hoeft niet alle afhankelijkheden van alle afhankelijkheden van alle afhankelijkheden enzovoort op te schrijven, maar je moet op zijn minst de afhankelijkheden van je pakketten en hun afhankelijkheden opschrijven.

5692759 53
5692759 53

Stap 2. Zorg ervoor dat je toestemming hebt om alle media te gebruiken

Dit geldt voor alle afbeeldingen, inclusief 3D-modellen, muziek, dialogen, muziek, bibliotheken en frameworks die je voor je game hebt gebruikt. Alles wat je niet zelf hebt geschreven.

  • Vaak zijn er enkele voorwaarden, zoals het vermelden van de auteur of het delen van wijzigingen van de media onder dezelfde licentie. Soms kun je afbeeldingen gebruiken zonder de makers toe te wijzen, zolang je geen kosten in rekening brengt voor het spel. Als je de auteur moet vermelden, doe dit dan op een goed zichtbare plaats, zoals een tabblad "Credits" in je spel.
  • Er zijn ook media met copyright geclaimd en geen licentie gespecificeerd, soms met wat tekst zoals "Alle rechten voorbehouden". Als dat het geval is, moet je expliciete toestemming van de auteur krijgen voordat je het in je spel kunt opnemen.
  • Bibliotheken worden meestal vrijgegeven onder licenties waardoor ze als bibliotheek kunnen worden gebruikt. Een opvallende uitzondering is de GPL zonder koppelingsuitzondering: met een dergelijke licentie mag deze alleen worden gebruikt in een programma met bepaalde licenties. En u moet altijd ten minste de basispunten van de licentie lezen om er zeker van te zijn dat alles wat u met de media of bibliotheek doet, is toegestaan.

Waarschuwing: Als u media of bibliotheken gebruikt op een manier die de licentie niet toestaat in een spel dat u publiceert, kunt u in ernstige juridische problemen komen. Vraag het dus aan de auteur of vermijd het stuk media helemaal als u niet zeker weet of uw gebruik is toegestaan.

5692759 54
5692759 54

Stap 3. Bepaal onder welke voorwaarden je je spel wilt publiceren

Ga je je spel verkopen? Wilt u anderen toestemming geven om uw afbeeldingen en ideeën te gebruiken? Hoewel je voorzichtig moet zijn met de media die je in je project gebruikt, kun je meestal zelf beslissen hoe je anderen wilt toestaan je spel te gebruiken. Je kunt een Creative Commons CC0-licentie gebruiken om je game in het publieke domein uit te brengen. Om distributie en wijziging onder bepaalde voorwaarden toe te staan met behoud van enkele rechten, probeer je de Gnu General Public License (GPL) of de Berkeley Software Distribution (BSD)-licentie. Of u kunt uw software bedrijfseigen maken, wat inhoudt dat niemand deze mag verspreiden of wijzigen zonder uw toestemming.

Hoewel het mogelijk is om geld te verdienen door spellen te verkopen, is het onwaarschijnlijk dat mensen je eerste spel zullen kopen dat meestal weinig functies en niets bijzonders heeft. En als een gratis programma niet werkt, zullen de mensen die het hebben gedownload gewoon teleurgesteld zijn. Als ze ervoor hebben betaald, zullen ze echter hun geld terugeisen, wat meer problemen veroorzaakt voor zowel u als de gebruikers. Overweeg dus om uw eerste paar programma's gratis beschikbaar te stellen

5692759 55
5692759 55

Stap 4. Bepaal hoe je je game wilt publiceren

Elke methode heeft enkele voor- en nadelen, dus je moet zelf beslissen.

  • Publiceren op een website:

    Als je een website hebt, kun je je spel uploaden om het beschikbaar te maken voor download. Zorg ervoor dat u duidelijke instructies geeft over hoe u de software installeert, evenals alle vereiste afhankelijkheden. Het nadeel hiervan is dat spelers afhankelijkheden handmatig moeten installeren, wat voor sommige mensen moeilijk kan zijn.

  • Een pakket maken voor een pakketbeheerder:

    Er zijn verschillende pakketbeheerders, zoals apt, Yum en Homebrew, die het voor mensen gemakkelijk maken om apps te installeren in Linux en Linux-gebaseerde omgevingen. Ze hebben allemaal verschillende pakketformaten. Het goede aan pakketten is dat ze automatisch alle afhankelijkheden installeren (als je ze correct configureert). De speler hoeft dus alleen jouw pakket te installeren en kan vervolgens het spel spelen. Het probleem is dat er veel verschillende pakketbeheerders zijn op verschillende platforms, dus je zult wat werk moeten verzetten om pakketten te leveren voor de meest voorkomende.

5692759 56
5692759 56

Stap 5. Richt de aandacht op je programma

Overweeg om uw programma te uploaden naar een grote pakketrepository, zoals die welke Ubuntu en Debian onderhouden, om eenvoudige installaties mogelijk te maken. Post ook op de juiste forums, zoals de projectensectie van GameDev of een deel van tigSource. Maar wees niet teleurgesteld als je eerste games niet beroemd worden. Als je een idee hebt dat veel mensen leuk vinden, kan je spel bekend worden.

Tips

  • Wees geduldig en bereid om te leren. Programmeren kan soms frustrerend zijn!
  • Als je je afvraagt hoe iets in een andere game wordt gedaan, en de game is open-source, kun je de broncode bekijken.
  • Probeer bij het zoeken naar media inhoud te vinden die zich in het publieke domein bevindt. Zoek naar afbeeldingen en muziek van "Creative Commons" of "Public Domain" en gebruik websites zoals https://opengameart.org of
  • Kopieer geen grote stukjes code zonder de licentie te controleren. Het is vaak verboden, en als dat niet het geval is, is meestal bronvermelding vereist.
  • Maak geen spam of post niet op ongepaste plaatsen wanneer u uw game promoot. Hierdoor wordt u waarschijnlijk geblokkeerd van de pagina, is het gewoon vervelend en schaadt het uw reputatie.

Aanbevolen: