PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [VX-Ace] Script zeigt Bild nicht an



Elster
28.03.2015, 13:51
Hallo zusammen ^^

Ich arbeite gerade an einem Script für ein Memory und habe momentan ein großes Problem, mein Bild wird nicht angezeigt.

Das Debakel sieht bis nun so aus:


def draw_graphic
@graphic = Sprite.new

if $modus == 1
#@graphic.bitmap = Cache.picture("Grundkarte.png") rescue nil
end
if $modus == 0
@graphic.bitmap = Cache.picture("Testkarte.png", 1, $x_1, $y_1, 100, 100,
255, 0) rescue nil
end

end


In den Variablen $x_1 und $y_2 stehen Werte. Eigentlich war es von mir angedacht damit das Bild richtig auf dem Screen zu platzieren. (Habe auch via Konsole geprüft ob in den Beiden was drin steht, tut es und auch der modus ist 0.)

Mein Versuch "Number" mitzuliefern sieht wie folgt aus:


if $modus == 0
@graphic.bitmap = Cache.picture[1].show("Testkarte.png", 1, $x_1, $y_1, 100, 100,
255, 0) rescue nil
end

Bekomme aber nur einen schwarzen Bildschirm geliefert.
Wenn ich das "rescue nil" wegnehme schmiert mir Spiel ab. So dann auch mal zwischendrin die Frage, was macht dieser Befehl überhaut. Habe ihn in anderen Scripten mit Bildern immer wieder gesehen.

Ein Bild wird mir zudem angezeigt wenn ich einfach sage:


@graphic.bitmap = Cache.picture("Testkarte.png")


Aber das ist ja nicht das was ich möchte. Dann ist das Bild stumpf oben links in der Ecke und zudem möchte ich ja auch mehrere anzeigen.

Natürlich kann man so ein Memory auch leicht ohne Script basteln, aber ich möchte es unbedingt mit hinbekommen.

Wäre super lieb wenn mir hier wer auf die Sprünge helfen könnte.

Cepanks
28.03.2015, 14:22
Mit der Position hat das Bitmap nichts am Hut, das wird über den Sprite geregelt. Die beiden zusammen kann man sich ein bisschen vorstellen wie eine Leinwand (Sprite) auf die eben was gemalt wird (Bitmap). Die Leinwand mit dem Gemalten wird dann irgendwo platziert.

Was du machen musst, ist also folgendes:


sprite = Sprite.new
sprite.bitmap = Cache.picture('Testkarte.png')
sprite.x = $_x1
sprite.y = $_y1

Cache.picture holt einfach nur ein Bitmap aus dem Cache, wenn es da drin ist, ansonsten wird von der Festplatte geladen. Das spart Zeit und Speicher falls eben dieses Bitmap noch öfters gebraucht wird. Verschiedene Leinwände teilen sich dann quasi ein Gemälde. Wenn du hingegen fünf mal direkt Bitmap.new('Graphics/Pictures/meinbild.png') nutzt, hast du am Ende unnötigerweise fünf Mal ein identisches Bitmap im Speicher, das auch jedes Mal wieder neu von der Festplatte geladen werden muss.

rescue nil ist übrigens eine dumme Idee, weil du damit den Fehler dort unterdrückst wo er passiert und dann je nach Script ziemlich sicher später an anderer Stelle eine Fehlermeldung bekommst, deren Ursprung auf den ersten Blick nicht zu erkennen ist.



Edit: Achso, falsch verstanden. Du wolltest wissen, was es mit dem rescue auf sich hat, nicht mit dem Cache? :D

Wie gesagt, damit werden Fehler abgefangen.

In deinem Beispiel ist der Cache.picture-Aufruf fehlerhaft, deshalb wird stattdessen das getan, was hinter dem rescue steht, in deinem Fall einfach ein allein stehendes nil. Dem Sprite wird also nie ein Bitmap zugewiesen, deshalb bleibt der Bildschirm schwarz.

Elster
28.03.2015, 17:56
Klasse, danke.
Ein Bild juhu :D

Aber... wie bekomme ich jetzt mehrere Bilder auf einmal angezeigt?
Immer wieder einen neuen sprite[nummer] = Sprite.new erzeugen klappt ja nicht (ja ich habs versucht). Da wird nur ein Bild angezeigt und das Vorherige ausgeblendet.
Bin sowieso ein wenig verwundert, der Fehler liegt vermutlich weiter oben im Code, aber nach ein paar Sekunden verschwinden mein Bild auch einfach wieder.
Ich glaube ich brauche noch einen Schubser in die richtige Richtung :confused:

Cepanks
29.03.2015, 10:02
Sprites in RGSS haben keine Nummern. Du musst für jeden Sprite eine neue Variable verwenden, sonst wird der alte überschrieben. Was natürlich auch geht, ist ein Array, so werden auch die Pictures im Maker verwaltet. Das versuchst du scheinbar gerade.

Um genau sagen zu können warum dein Bild wieder verschwindet, fehlen Informationen. Hast du für dein Memory eine neue Szene erstellt oder versuchst du das irgendwo anders mit reinzuschreiben? Am besten wäre, wenn du mal dein komplettes Script zeigst.

Ein erster Tipp wäre, dass "sprite" nur eine lokale Variable (http://wiki.ruby-portal.de/Variable#Lokale_Variable) ist, die wieder verfällt, sobald Ruby mit deiner Methode durch ist, in der der Sprite erstellt wird. (War in meinem Beispiel auch so, aber das war eigentlich nur zur Demonstration von Sprites^^)

Elster
29.03.2015, 12:05
Also bis jetzt sieht das so aus:



class Memory < Scene_Base

#-------------------------------------------------------------------------------
# Startet nach und nach alle Methoden
#-------------------------------------------------------------------------------
def start
super
gegebenheiten
draw_graphic
end

#-------------------------------------------------------------------------------
# Legt die Grundvariablen und Arrays fest. Verteilt zudem die Koordinaten.
#-------------------------------------------------------------------------------

def gegebenheiten
# Hier wird der Modus grundlegend bestimmt.

if $game_switches[1] == true
$modus = 0
end
if $game_switches[2] == true
$modus = 1
end
if $game_switches[3] == true
$modus = 2
end

# IDs der Spielkarten, ihr Standort in dem Array bestimmt die Position
# auf dem Spielfeld. Zahlen kommen doppelt vor, da es von jeder Karte
# 2 gleiche gibt.
random = [
0, 0,
1, 1,
2, 2,
3, 3,
4, 4,
5, 5,
6, 6,
7, 7
].shuffle
# in diese Variablen werden die IDs aus dem Array gespeichert, zwecks
# Vergleich.
# mal schaun ob ich das so brauche
# $id_1 = 0
# $id_2 = 0

# Die Koordinaten lauten:
# 000 x 000 | 136 x 000 | 272 x 000 | 408 x 000
# 000 x 104 | 136 x 104 | 272 x 104 | 408 x 104
# 000 x 208 | 136 x 208 | 272 x 108 | 408 x 108
# 000 x 312 | 136 x 312 | 272 x 312 | 408 x 312
xy = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
0, 208,
136, 208,
272, 208,
408, 208,
#
0, 312,
136, 312,
272, 312,
408, 312
]
i = 0
j = 0
r = 0
# Hier kommt zusammen was zusammen gehört!
while i < 15 do
$xi = xy[j]
j = j + 1
$yi = xy[j]
j = j + 1
$r = random[r]
r = r + 1

if i == 0
$id_0 = $r
$x_0 = $xi
$y_0 = $yi
end
if i == 1
$id_1 = $r
$x_1 = $xi
$y_1 = $yi
p $x_1
p $y_1
end
i = i + 1
end
end

#-------------------------------------------------------------------------------
# Sorgt für das Anzeigen der Bilder
#-------------------------------------------------------------------------------

def draw_graphic
sprite = Sprite.new
sprite1 = Sprite.new

if $modus == 1

end
if $modus == 0
sprite.bitmap = Cache.picture("Testkarte.png")
sprite1.bitmap = Cache.picture("Spinne1.png")
sprite.x = $x_0
sprite.y = $y_0
sprite1.x = $x_1
sprite1.y = $y_1
end

end
end


Aufgerufen wird es mit dem Befehl halt
SceneManager.call(Memory)

Bis jetzt noch seeeehr umständlich geschrieben, aber erstmal soll es ja laufen, verfeinern kann man ja immer noch :3

-KD-
29.03.2015, 15:38
Hi,

du musst die Sprites "am Leben halten". Wenn du sie in lokale Variablen abspeicherst, werden sie irgendwann vom GarbageCollector gelöscht und die Grafik wird nicht mehr angezeigt.

Hierfür verwendest du am besten Instanzvariablen (also die mit dem @).

Globale Variablen solltest du möglichst vermeiden. Nimm am besten die globalen Variablen die die RGGS selbst definiert und füge dort deine eigenen Attribute hinzu.

Überhaupt macht es Sinn deinen Code mehr in Klassen zu organisieren, sonst wirst du schnell den Überblick verlieren.

Hier mal ein Beispiel wie das aussehen könnte:

class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize
@figure_names = []
@positions = []
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 64
@card_height = 64
# distance between cards
@margin = 12
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end


Das ist deine Game-Logik Klasse. Die verwaltet alle Attribute des Memory-Spiels sowie die Spiellogik dahinter. Was sie nicht macht ist das Anzeigen der Grafik und das entgegennehmen von Nutzereingaben. Das regelst du über die Scene. Als nächstes speicherst du dieses Memory-Objekt in ein bestehendes globales Objekt ab. z.B. Game_System


class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end

Jetzt kannst du ein neues Memory-Spiel mit


$game_system.memory = Game_Memory.new

anlegen.

Als nächstes legst du deine Szene-Klasse an. Hier musst du dir klar machen das Grafiken in einer Szene einen Lebenszyklus haben: Jede Grafik muss angelegt, geupdatet und am Ende der Szene wieder gelöscht werden. Dafür legst du entsprechend drei Funktionen an:

def initialize_graphics
# for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
end

def update_graphics
# update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

Das updaten ist erstmal nicht so wichtig, solange du die Positionen der Karten nicht änderst. Wenn du aber neue Funktionen einfügst, wie z.B. das der Nutzer Karten entfernen kann, müssen diese Aktionen Auswirkungen auf das Anzeigen der Grafiken haben. Das regelst du in dem Update-Zyklus. Sprich: Wenn der Nutzer eine Karte abhebt änderst du die Variablen in $game_system.memory. Beim nächsten Updaten der Grafiken werden diese Änderungen dann sichtbar.

Ich hoffe ich hab dir nicht zu viel "vorgesagt". Aber ich denke es gibt noch genug zu tun. So ein Memory-Spiel ist eine gute Übung für das Scripten in der RGSS.

Ein paar Vorschläge was man noch bessern könnte:
- wenn du viele Grafiken verwalten musst, legt für diese eine neue Klasse Spriteset_Memory an. Dann musst du weniger Code in deine Szene-Klasse legen.
- genauso macht es evtl. Sinn die Logik hinter den Spielkarten in eine eigene Game_MemoryCard Klasse auszulagern. Die Klasse Game_Memory verwaltet dann einen Array von Game_MemoryCard Objekten, die Methoden zum Abfragen der Position etc. haben
- genauso kannst du eine Klasse Sprite_GameCard schreiben die eine Referenz auf Game_MemoryCard hat und weiß wie sie grafisch angezeigt werden

Elster
31.03.2015, 12:06
Danke euch Zwei so weit, aber ich glaube ich noch was an dem Code von -KD- falsch verstanden.

Zum Verständnis...
In das Array
@figure_names = [] kommen alle Bilder rein die ich anzeigen möchte oder?
zum Beispiel sehe das dann so aus
@figure_names = ["Testkarte.png"] oder?

Sollte das so weit stimmen, anderes Verständnisproblem.


def initialize_graphics
# for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
end
.

Muss ich das für jede Karte machen? Bis jetzt kam es mir so vor, als würde das der Code für alle schon regeln, glaube aber hier etwas arg falsch verstanden zu haben.
Momentan kommt mir der dumpfe Gedanke... dass die Zeile
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
so aussehen müsste:
@card_sprites = $game_system.memory.get_cards.map do |0, 0, "Testbild.png"|
Wobei ich mich dann natürlich auch wieder frage, wofür ich vorher
@figure_names und
@positions habe. Mir war so genau diese müssten dafür da sein.
Natürlich lagen die beiden Array in einer Klasse, wodurch das zusammenhängen kann das ich das noch einmal machen muss, dennoch bin ich momentan arg verwirrt, da ich stark davon ausgehe dass der Code von -KD- garantiert so funktioniert... unter Voraussetzung man setzt ihn richtig ein.
Kompelieren tut er... nur wie immer sehe nichts XD ... wegen weil falsche Bedienung meinerseits.

Hilfe ^^"

-KD-
02.04.2015, 00:32
Hi,

ich hab den Code nicht ausprobiert. Gut möglich das da was noch nicht funktioniert.


In das Array kommen alle Bilder rein die ich anzeigen möchte oder?
Jap


Muss ich das für jede Karte machen? Bis jetzt kam es mir so vor, als würde das der Code für alle schon regeln, glaube aber hier etwas arg falsch verstanden zu haben.
Nein, das macht es automatisch für alle Karten. Die map Funktion bildet einen Array (oder eine beliebige andere Collection) auf einen neuen Array ab, in dem es eine Funktion auf jedes Element des Arrays ausführt.
Beispiel: Du hast eine Liste von Zahlen [1,2,3,4,5] und wendest darauf ein map mit der Quadrat-Funktion an. Dann bekommst du eine Liste [1,4,9,16,25] zurück. Vom Code her würde das folgendermaßen aussehen:

zahlen = [1,2,3,4,5]
# entweder
quadratzahlen = zahlen.map {|x| x**2 }
# oder
quadratzahlen = zahlen.map do |x|
x**2
end

# das ist exakt dasselbe wie
quadratzahlen = []
for zahl in zahlen do
quadratzahlen << zahl**2
end

Ob du geschweifte Klammern oder do...end benutzt ist egal. Was da zwischen den |...| steht sind die Parameter der Funktion, die du map übergibst.

In dem Beispielcode

# for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
sagst du: Lege einen Array an: für jede Karte, die $game_system.memory.get_cards zurückliefert, erzeuge einen Sprite, setze dessen x und y Koordinaten auf die Koordinaten der Karte, sowie seine Grafik auf die Grafik der Karte. Füge diesen Sprite dann in den Array ein. Setze am Ende die Variable @card_sprites auf diesen Array.

Der Code ist gleichbedeutend zu

@card_sprites = []
for x, y, image in $game_system.memory.get_cards do
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
@card_sprites << sprite
end


map gehört zu den Iteratorfunktionen (in anderen Sprachen auch Funktoren genannt). Das sind Methoden, die eine Funktion (also ein Stück ausführbaren Code) als Parameter bekommen.

In meinen Codebeispielen sind noch zwei weitere Iteratorfunktionen: each führt eine Funktion für jedes Element des Arrays aus (ohne dabei aber einen neuen Array zu erzeugen).

each ist identisch mit der For-Schleife.

zahlen = [1,2,3,4,5]
zahlen.each do |zahl|
print zahl
end
# ist gleichbedeutend zu
for zahl in zahlen do
print zahl
end

n.times führt eine Funktion n Mal aus. Sie entspricht einer Zählerschleife in anderen Sprachen.

5.times do
print "Hallo Welt"
end
# ist gleichbedeutend mit
for i in 1..5 do
print "Hallo Welt"
end

# times darf auch die Index-Variable als Parameter bekommen
5.times do |i|
puts "dies ist die #{i}te Wiederholung
end
# ist gleichbedeutend mit
for i in 0..4 do
puts "dies ist die #{i}te Wiederholung
end

Das Tutorial ist sehr veraltet und bezieht sich noch auf Ruby 1.8 (und den RPGMaker XP), aber evtl. hilft dir die dortige Erklärung zum Verständnis von Iteratorfunktionen: http://www.rpg-studio.org/scientia/RGSS/Tutorials/Rubykurs_2_-_OOP_Teil_2

Elster
02.04.2015, 13:21
Hey ^^

Ich befinde mich gerade auf Fehlersuche und bin schwerst verwirrt.
Der scheint nur in die erste Methode einer Klasse zu gehen. Muss ich die anderen Klassen wie in meinem alten Code noch mal alle extra aufrufen?

Jedenfalls... er geht soweit ich das sehe nur in die Methode "initialize" (immer und immer wieder) und in die Klasse "Game_System", genau einmal.

Edit:
Wie ich es im alten Code gemacht habe funktioniert es leider nicht... warum geht der denn nicht in die anderen Methoden rein Oo
... oder sehe ich das einfach nur nicht... der müsste mir doch mit:


irgendwas = 99
p irgendwas


den Wert von "irgendwas" in der Konsole ausgeben. Egal wo ich mich befinde.

Kelven
02.04.2015, 14:37
Ja, vermutlich wird die Stelle im Code nicht erreicht. <initialize> wird immer dann aufgerufen, wenn ein neues Objekt der Klasse angelegt wird. Hast du beispielsweise die Klasse Auto und schreibst: auto = Auto.new, dann wird <initialize> von Auto einmal aufgerufen. Die anderen Methoden der Klasse werden dann aufgerufen, wenn du im Code explizit auto.[Name der Methode] schreibst.

-KD-
02.04.2015, 20:51
Automatisch geht er in keine Methode rein. Wie Kelven schon gesagt hat: die initialize Methode wird aufgerufen sobald du Klasse.new schreibst.

Während das Spiel läuft wird ständig SceneManager.scene.main aufgerufen. Dadurch das du SceneManager.call(Memory) geschrieben hast, wird die Klasse Memory als aktive Szene gesetzt und zuerst die initialize Methode und danach die main Methode von Memory aufgerufen.
Da deine Memory Klasse von Scene_Base erbt, übernimmt sie deren main Methode. Wenn du also wissen willst, was main macht, musst du in die Klasse Scene_Base reinschauen. Dort siehst du, dass main erst die Methode start aufruft, und danach in einer Schleife die Methode update aufruft bis die Scene beendet wird. Danach wird die Methode terminate aufgerufen.

In der start-Methode hast du dann dein draw_graphic aufgerufen.

Du müsstest jetzt noch die update Methode überschreiben und dort update_graphics aufrufen, sowie die terminate Methode überschreiben und dort dispose_graphics aufrufen (und wichtig dabei: in den Methoden immer am Anfang das Schlüsselwort super schreiben, damit die gleichnamige Methode der Superklasse Scene_Base aufgerufen wird).

Elster
04.04.2015, 13:59
Also... wenn ich das richtig verstanden habe... muss jetzt bei Scene_Base folgendes tun.



def update
update_basic
update_graphics
end


Selbiges halt bei "terminate" mit dem anderen Befehl.
So weit so gut, weiterhin, wenn ich -KD- richtig verstanden habe, jede meiner Methoden mit "super" ausstatten.
Wobei das nicht für update_graphics und dispose_graphics zu gelten scheint.
So weit so gut und verstanden... hoffe ich. Oder soll ich "update_basic" rauswerfen O_O (kann ich mir eigentlich nicht vorstellen... das braucht man sicherlich.)

Weiterhin, wenn ich es richtig verstehe, brauche ich "def start" nicht mehr, oder?

Sooo... sollte ich nun alles richtig haben, nahezu überall super drin, in terminate und update die beiden Befehle eingefügt... dann kann mir sicher noch wer erklären was dieser Fehler zu bedeuten hat.


Script 'Memory' line 135: no MethodError occurred.
undefined Method `each_with_index' for nil:NilClass


Diese Meldung taucht sofort beim Starten des Spiels auf. Hab das extra noch mal in ein neues Projekt gepackt um zu schauen ob es mit anderen Scripten Reibereien gibt.
Aber anscheinend mag er da was gar nicht... was jedoch verstehe ich nicht, soweit ich mir "each_with_index" angeschaut habe, ist es genau für diesen Fall gedacht. Einen hash aus einem Objekt und seinem Index zu bilden. http://apidock.com/ruby/Enumerable/each_with_index
Habe ich doch bei den "leichten" Schritten was mal wieder falsch verstanden?

-KD-
04.04.2015, 15:35
Also... wenn ich das richtig verstanden habe... muss jetzt bei Scene_Base folgendes tun.
An Scene_Base solltest du gar nichts verändern. Nur deine Memory Klasse muss geändert werden.

Schau dir mal dieses Diagramm an: http://www.multimediaxis.de/attachment.php?attachmentid=22154&stc=1&d=1428157342

Das zeigt in welcher Reihenfolge die Methoden aufgerufen werden. Die Schreibweise Klasse#methode bedeutet: die Methode ist eine Instanzmethode der jeweiligen Klasse. Die Schreibweise Klasse.methode bedeutet: Die Methode ist eine Klassenmethode (kann also direkt aufgerufen werden, wie SceneManager.call).

Wenn du eine eigene Scene-Klasse anlegst, die von Scene_Base erbt, kannst du Methoden überschreiben. Das heißt: Schreibst du in deiner Klasse eine update Methode, so wird diese anstelle der update Methode in Scene_Base aufgerufen. Die Methoden in Scene_Base sind aber wichtig, sie sorgen zum Beispiel dafür das Tastatureingaben abgefragt und der Bildschirm neu gezeichnet wird. Aus dem Grund musst du, wann immer du eine Methode von Scene_Base überschreibst, darin super aufrufen. super bedeutet: rufe die Methode der Superklasse (also Scene_Base) auf.

Beispiel: Du schreibst in deiner Memory Klasse eine update Methode mit dem Inhalt:


def update
mache_dies
super
mache_jenes
end

Dann passiert folgendes:
1. Zuerst wird Memory#mache_dies aufgerufen
2. Danach wird Scene_Base#update aufgerufen.
3. Danach wird Memory#mache_jenes aufgerufen

Wenn du nun in Scene_Base#update schaust, siehst du, dass dort update_basic aufgerufen wird (diese Methode zeichnet den Bildschirm neu und nimmt Tastatureingaben entgegen). Du musst also update_basic nicht selbst aufrufen, wenn du mit super bereits die update Methode der Superklasse aufgerufen hast.


Diese Meldung taucht sofort beim Starten des Spiels auf. Hab das extra noch mal in ein neues Projekt gepackt um zu schauen ob es mit anderen Scripten Reibereien gibt.
Aber anscheinend mag er da was gar nicht...
Der entscheidende Teil der Fehlermeldung ist for nil:NilClass. Das bedeutet soviel wie: Die Variable, mit der du each_with_index aufrufst, ist leer.

In meinem Beispiel wäre das die Variable @card_sprites. Dieser Variable wurde noch kein Wert zugewiesen, zu dem Zeitpunkt wo each_with_index aufgerufen wird.

In meinem Beispiel wird die Variable @card_sprites in der Methode initialize_graphics angelegt. Offenbar rufst du diese Methode nicht auf. Sie sollte innerhalb von start aufgerufen werden.

Lege also eine Methode Memory#start an, rufe dort mit super die gleichnamige Methode von Scene_Base auf und danach die Methode initialize_graphics.


Dwas jedoch verstehe ich nicht, soweit ich mir "each_with_index" angeschaut habe, ist es genau für diesen Fall gedacht. Einen hash aus einem Objekt und seinem Index zu bilden. http://apidock.com/ruby/Enumerable/each_with_index
Habe ich doch bei den "leichten" Schritten was mal wieder falsch verstanden? Mit each_with_index kannst du über eine Collection (z.B. einen Array) iterieren (also eine Schleife bauen), wobei du in jedem Schritt sowohl das jeweilige Element als auch dessen Position/Index bekommst.


Falls du mit Ojektorientierter Programmierung noch nicht vertraut bist, kannst du dir ja mal diesen Teil des Tutorials durchlesen: http://www.rpg-studio.org/scientia/RGSS/Tutorials/Rubykurs_2_-_OOP_Teil_1

Elster
06.04.2015, 21:34
Erneut muss ich mit Kleinigkeiten nerven... langsam tut es mir echt leid...

Ich habe nun folgende Methoden angelegt:



def start
super
initialize_graphics
end




def update
super
update_graphics
end




def terminate
super
dispose_graphics
end


start ist gleich die erste Methode und ich habe sie am Ende von "initialize" aufgerufen, da "initialize" ja nun mal immer zuerst startet.
Nun habe ich das grandiose Problem, dass sich folgende Fehlermeldung kommt.



Script 'Game_Interpreter' line 1411: NoMethodError occurred.
super: no superclass method `start' for #<Game_Memory:0xe80c074>


Habe auch aus Frust versucht das in eine Klasse zu stecken, dass sah dann so aus:



class Memory < Scene_Base
def start
super
initialize_graphics
end
end


Gab dann aber auch nur eine Fehlermeldung:



Script 'Game_Interpreter' line 1411: NameError occurred.
undefined local variable or method `start' for
#<Game_Memory:0xe294c7c>



Ich kann mir das gerade nur so erklären, dass ich a) beim Aufruf von start was falsch mache oder die Bedingungen für start nicht stimmen.
Bin auch nebenher dabei mir das über objekt orientierte Programmierung durchzulesen (weiß ich eigentlich alles... aber ich kann auch alles falsch verstanden haben.)
Irgendwo in meinen Gedankengängen scheint echt der Wurm drin zu sein...

PS -KD- : Der erste Link geht nicht.

Kelven
06.04.2015, 22:05
Der erste Fehler kommt daher, dass super in diesem Fall versucht, die Methode start von der übergeordneten Klasse aufzurufen, die hier anscheinend Game_Memory ist. Wenn ich alles richtig verstanden hab, soll aber deine Klasse Memory von Scene_Base erben, also ist class Memory < Scene_Base eigentlich richtig. Der zweite Fehler kommt dann her, dass jemand anderes trotzdem noch versucht, start vom Game_Memory aufzurufen.

Cepanks
06.04.2015, 22:19
start ist gleich die erste Methode und ich habe sie am Ende von "initialize" aufgerufen, da "initialize" ja nun mal immer zuerst startet.
"start" - und auch alle anderen Methoden, die am Ablauf der Szene beteiligt sind, also "update", "terminate", "perform_transition" etc. - müssen von dir gar nicht selbst aufgerufen werden, darum kümmert sich der SceneManager eigentständig, wenn du ihm mittels SceneManager.call oder SceneManager.goto sagst, dass jetzt ein Szenenwechsel stattfinden soll.

-KD-
07.04.2015, 11:55
PS -KD- : Der erste Link geht nicht.

Das ist ja echt ärgerlich. Hab irgendwie noch nicht gerafft wie man Bilder an den eigenen Post anhängt. Hab ein Diagramm hochgeladen, aber das wurde danach prompt von der Forensoftware gelöscht.

Egal, dann eben in Textform:

Was ich mit dem Diagramm eigentlich zeigen wollte, ist welche Methoden in welcher Reihenfolge aufgerufen werden. Das ist in einem fertigen Spiel nicht immer so leicht herauszufinden und erschwert natürlich die Fehlersuche, wenn dir gar nicht klar ist, warum welche Methode wann aufgerufen wird.

Das ganze Spiel beginnt im "Main" Script mit der Zeile

rgss_main { SceneManager.run }

rgss_main ist eine Funktion der RGSS die sagt: Führe den Codeblock einmal aus. Drückt der Spieler dabei die F12 Taste, wird der Codeblock von neuem ausgeführt (ergo, das Spiel neugestartet). Ist also erstmal nicht so wichtig. Wichtig ist: SceneManager.run wird ausgeführt.

Als nächstes guckst du also was SceneManager.run macht.

module SceneManager
# ...
def self.run
DataManager.init
Audio.setup_midi if use_midi?
@scene = first_scene_class.new
@scene.main while @scene
end
end

Okay, SceneManager.run ruft zuerst DataManager.init auf. Die Definition dazu findest du im Script "DataManager". Kurz zusammengefasst: DataManager.init liest die Datenbank des Makers ein (die Datenbank sind alle Einstellungsmöglichkeiten die du im Maker hast, wenn du F9 drückst, z.B. Helden, Monster, Items etc.). Danach werden alle Game-Objekte angelegt. Kleiner Exkurs: Alle Game-Objekte haben einen Klassennamen der mit Game_ anfängt. Sie enthalten den aktuellen Zustand des Spiels. Du kannst dir leicht merken: Alles was in einen Spielstand abgespeichert werden muss (was beim Neuladen also wieder verfügbar sein muss) ist Teil eines Game-Objektes. Denn nur Game-Objekte werden gespeichert. Dem gegenüber gibt es Daten-Objekte. Daten-Objekte fangen alle mit RPG:: an, z.B. RPG::Actor. Sie enthalten die statischen, unveränderlichen Inhalte, die du im Maker definiert hast. Sie müssen nicht im Spielstand abgespeichert werden, weil sie konstant für alle Spielstände sind. Kleines Beispiel: RPG::Actor enthält für jedes Level die zugehörigen Lebenspunkte. Game_Actor enthält die tatsächlichen Lebenspunkte des Helden, mit Inbegriffen also auch Lebenspunkte die man durch Trinken eines Zaubertranks o.ä. erhält. RPG::Actor enthält den Namen des Helden in der Datenbank. Game_Actor enthält den tatsächlichen Namen des Heldens (der sich im Spiel z.B. durch Umbenennung ändern kann). Darum macht es Sinn für dein Minispiel eine Klasse Game_Memory anzulegen, die die veränderlichen Zustände deines Memory-Spiels enthält (welche Karten liegen auf dem Tisch, welche Karten wurden gezogen, wie viele Punkte hat der Spieler usw.).

Zurück zum Spielfluss: Nach dem Aufruf von DataManager.init wird mit

@scene = first_scene_class.new
die erste Scene angelegt und in die Variable @scene gespeichert. first_scene_class ist eine Methode, die die Klasse zurückgibt mit deren Scene das Spiel beginnen soll (z.B. Scene_Title). @scene ist eine Variable, welche die aktuelle Scene des Spiels beinhaltet.

Danach kommt

@scene.main while @scene
Achtung: Das ist eine Schleife. Die Methode @scene.main wird jetzt solange ausgeführt solange die Variable @scene nicht nil ist. An diesem Punkt befinden wir uns in der Hauptschleife des Spiels. Jetzt wird immer @scene.main aufgerufen, bis das Spiel beendet wird. Das Beenden des Spiels geschieht durch den Aufruf von SceneManager.exit. Wenn du in die Methodendefinition guckst, siehst du, dass diese Methode einfach die Variable @scene auf nil setzt (und damit die Schleifenbedingung verletzt, wodurch die Schleife abbricht).

Jede Scene-Klasse im Spiel erbt von Scene_Base. Wenn du wissen willst was @scene.main macht schaust du also am besten erstmal dort hinein:


class Scene_Base
# ...
def main
start
post_start
update until scene_changing?
pre_terminate
terminate
end
# ...
end
Zuerst wird Scene_Base#start aufgerufen. Danach Scene_Base#post_start. Dann kommt wieder eine Schleife: Solange die Hauptscene nicht geändert wird (du also nicht SceneManager.call oder SceneManager.exit aufrufst) wird die Methode Scene_Base#update aufgerufen. Wird die Scene beendet, so werden pre_terminate und terminate_aufgerufen.

Was hat es mit dem start und post_start bzw. pre_terminate und terminate auf sich? Hier geht es darum einen Übergang zwischen zwei Scenen zu erzeugen. Wenn du z.B. von der Map ins Menü wechselst, so geht das nicht abrupt, sondern die Map wird langsam ausgeblendet und das Menü wird langsam eingeblendet. start zeichnet den neuen Bildschirm der neuen Scene. post_start erzeugt den Übergang. Wenn du post_start überschreibst und eigenen Code einfügst, so wird dieser erst ausgeführt, nachdem die Scene eingeblendet wurde. Alles was in start steht wird ausgeführt, bevor die Scene eingeblendet wird. Dasselbe gilt für pre_terminate und terminate. In terminate wird der Bildschirm eingrefroren, so dass die nächste Scene gezeichnet werden kann. Alles was in pre_terminate reinkommt, wird noch sichtbar für den Spieler bevor die Scene ausgeblendet wird.
In der Regel brauchst du post_start und pre_terminate nicht.

Zuletzt noch update: update ruft erstmal nur update_basic auf. update_basic zeichnet den Bildschirm neu und fragt Tastatureingaben ab. update_basic brauchst du nicht überschreiben. In der Regel überschreibst du update und rufst als allererstes super auf um Scene_Base#update aufrufen (die dann update_basic aufruft).

Nochmal zusammengefasst:
1. Spiel startet mit SceneManager.run
2. Dieser ruft in einer Schleife immer wieder @scene.main auf
3. Diese führt start aus um sich zu initialisieren
4. und danach update in einer Schleife (solange die Scene existiert) auf
5. wird die Scene beendet ruft sie vorher noch terminate auf

Schreibst du eine eigene Scene so überschreibst du 3 Methoden: start, update und terminate. Alle drei überschriebenen Methoden sollten als allerersten Aufruf ein super enthalten, um die gleichnamige Methode der Superklasse aufzurufen. Eine Scene sollte den Ablauf eines Scriptes koordinieren. Sie regelt im Grunde genommen drei Elemente: Das Zeichnen aller Grafiken, Abspielen von Soundeffekten/Musik und das Abfragen von Tastatureingaben. Wird der grafische Teil sehr komplex, lagert man ihn in der Regel nochmal in eine eigene Klasse aus.
Die Spieldaten und Spielmechanik schreibt man in eine eigene Klasse. In der Regel nennt man sie Game_XYZ, z.B. Game_Memory. Hier kommt alles rein was einen Zustand deines Scriptes darstellt, der in einem Spielstand abgespeichert werden muss. In einem Memory-Spiel wären das: die Karten auf dem Spielbrett, die Karten auf der Hand des Spielers. Eine Instanz dieser Klasse packt man dann in eine bestehende Game_XYZ Klasse, z.B. Game_System. Danach kann man darauf z.B. mit $game_system.memory zugreifen.

Ich weiß nicht wie dein Code gegenwärtig aussieht. Aber ich vermute mal das dein Problem noch darin liegt zu erkennen, welcher Code in Game_Memory und welcher in Scene_Memory gehört (du nennst letztere Memory, aber es ist besser eine Scene Klasse mit dem Prefix Scene_ anfangen zu lassen).

Elster
12.04.2015, 13:20
Ein wenig entwirren konnte ich bis jetzt das Ganze.... ok ein ganz klein wenig.
Ich hatte noch den alten Code wo stehen, so dass ich Klassen doppelt hatte, womit das Script versucht hat die Klasse Memory aus meinem alten Code zu starten.
Beeindruckender Weise hat das irgendwann funktioniert wodurch ich diesen Fehler erst realisiert habe o_o
Mittlerweile habe die Klasse auch unbenannt...

Nun nachdem ich diesen Fehler weg habe, hänge ich wieder.
Und zwar hänge ich am Methodenaufruf.

Beispiel:


A)
class Scene_Memory < Scene_Base
def start
super
initialize_graphics
end
end

B)
class Scene_Memory < Scene_Base
def self.start
super
initialize_graphics
end
end


Wenn ich nun in der Klasse Game_Memory, in der Methode initialize am Ende folgenden Befehl aufrufe "SceneManager.call(Scene_Memory.start)" wird ja aus der Klasse "Scene_Memory" die Methode "start" aufgerufen. Ja... und hier komme ich zu meinem Knackpunkt. Bei A) gilt die Methode als nicht initialisiert, bei B) kann ich kein super darauf anwenden, da nun start von Scene_Memory erbt. Dafür komme ich in die Methode rein, nützt mir nur nicht viel, da nun die Methode "get_cards" die in "initialize_graphics" aufgerufen wird, nicht initialisiert ist oder leer ist.

Ich habe in der Methode initialize schon mit verschiedensten Aufrufen versucht an die Methode start zu kommen. Unter anderem "SceneManager.call(Scene_Memory.start.new)" was auch geht... nur eben mit den selben Problemen. Auch ein einfacher Aufruf aller "start" oder "Scene_Memory.start" bringt mich in die selbe Lage.
Mein Versuch einfach "SceneManager.call(Scene_Memory)" aufzurufen ... lief darauf hinaus, dass er nicht in die Methode rein ging... habe auch nichts anderes erwartet.

Ich poste hier einfach noch mal Alles rein, großartige Änderungen zum Code von -KD- gibt es noch nicht, ich will erstmal das es so weit läuft. Klar... im Nachhinein andere Sachen einbauen ist nie die klügste Idee... aber wenn es nicht läuft ist es auch doof groß dran herumzuschrauben.

Bei dieser Variante des Codes handelt es sich um jene, wo er keine Daten in get_cards findet.



class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat
@modus = 0
@move = 50

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize
@figure_names = ["Spinne1.png", "Spinne2.png", "Spinne3.png", "Spinne4.png",
"Spinne5.png",
"Spinne6.png", "Spinne7.png", "Spinne8.png", "Spinne9.png", "Spinne10.png",
"Spinne11.png",
"Spinne12.png", "Spinne13.png", "Spinne14.png", "Spinne15.png", "Spinne16.png"]

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
0, 208,
136, 208,
272, 208,
408, 208,
#
0, 312,
136, 312,
272, 312,
408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 64
@card_height = 64
# distance between cards
@margin = 12
p @positions
SceneManager.call(Scene_Memory.start.new)
#Scene_Memory.start
#SceneManager.call(Scene_Memory.start)
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end

class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end

def initialize_graphics
# for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
end

def update_graphics
# update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

# Erbebt von Scene_Base
class Scene_Memory < Scene_Base
#class << self
#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def self.start
#super
initialize_graphics
update
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics
end

#end
end
#end


Die Fehlermeldung lautet um genau zu sein:


Script 'Game_Interpreter' line 1144: NoMethodError occurred.
undefined method `get_cards' for nil:NilClass


Ergo wurde wohl wieder etwas noch nicht aufgerufen, wodurch ich noch nicht an die Daten komme.
Der Methode zufolge sollte es sich hierbei ja um get_card und den index davon handeln.
Jedoch kann das so wie es da ist, sowieso noch nicht stimmen, immerhin kann ich kein "super" ausführen.
Wie merkt meine Klasse, dass die Methode da ist, ohne das ich self.start schreiben muss?
Das würde dann hoffentlich auch die Folgeprobleme beheben...

-KD-
16.04.2015, 19:12
B)
class Scene_Memory < Scene_Base
def self.start
super
initialize_graphics
end
end
Wenn du self.xxx bei einer Methodendefinition schreibst, wird die Methode zur Klassenmethode (du kannst sie also über Klassenname.methodenname aufrufen). Klassenmethoden können ihrerseits keine Instanzmethoden aufrufen, sie beziehen sich nur auf die Klasse. Klassenmethoden braucht man eher selten. In deinem Fall brauchst du sie jedenfalls gar nicht. Also weg mit den self.



class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat
@modus = 0
@move = 50
Dieser Code macht was völlig anderes als du wahrscheinlich vermutest. Instanzvariablen, die du in den Klassenblock schreibst, werden zu Klassenvariablen (die du dann innerhalb einer Klassenmethode nutzen kannst). Das ist eigentlich NIE das was du willst. Daher gleich abgewöhnen! Instanzvariablen schreibst du in die Initialize-Methode rein.



p @positions
SceneManager.call(Scene_Memory.start.new)
#Scene_Memory.start
#SceneManager.call(Scene_Memory.start)
Das hat nichts in der initialize Methode zu suchen. Wenn du deine Memory-Szene starten willst, mache das entweder über ein Event im Spiel (mit dem Call Script Befehl). Oder, wenn du willst das das Spiel direkt mit dem Memory-Spiel beginnt, du schreibst

module SceneManager
# hier ist das self. ausnahmsweise mal erlaubt...
def self.first_scene_class
Scene_Memory
end
end

Das Problem warum dein Code nicht funktioniert ist, dass die Methoden initialize_graphics, update_graphics und dispose_graphics nicht in der Scene_Memory Klasse stehen. Du hast sie einfach lose in den Scripteditor eingefügt.

Elster
30.04.2015, 20:17
Entschudige bitte -KD- das ich hier so lange geschwiegen habe ^^" Mein Rechner hat den Geist aufgegeben... teilweise -.-
Danke so weit für deine großartige Hilfe ^^

Ich hab mit hier noch mal das Meiste durchgelesen um mit meinem jetzigen Problem klar zu kommen.
Habe brav die Methoden in die Klasse ingepflegt und "start" ganz nach unten gepackt. Mir Videos zu Programmierung mit Ruby im Verbindung mit dem VX Ace angeschaut (speziell zu Verbung) und aaaaah ... ich glaube ich scheitere am Aufruf.


$game_system.memory = Game_Memory.new
Ist ja der Code mit dem ich über Event -> Script halt Game_Memory starte.

So und mit:
SceneManager.call(Scene_Memory) sollte ich rein theoretisch doch Scene_Memory starten können oder?

Also im Prinziep sollte es insgesammt wie folgt aussehen.
In einem Event mit dem Script Befehl folgendes ausführen:


$game_system.memory = Game_Memory.new
SceneManager.call(Scene_Memory)


Joar... Game_Memory wird dann auch einmal gestartet... was dann passiert verwundert mich jedoch etwas.
Folgende Fehlermeldung taucht dann auf:

Script 'Game_Interpreter' line 1411: NoMethodError occurred.
undefined method `memory='for nil:NilClass

Was natürlich auch noch sein kann ist, dass er meint in der Klasse stünde nichts drin.
Bedeutet ich müsste vermutlich am Ende der Klasse "start" aufrufen.
Also wie folgt:


b = Scene_Memory.new
b.start


Wobei er sich dann über folgenden Codeteil beschwert.

@card_sprites = $game_system.memory.get_cards.map do |x, y, image|

Da kommt dann folgende Fehlermeldung.

Script 'Memory_3' line 118: NoMethodError occurred.
undefined method `memory' for nil:NilClass

memory scheint aus der Klasse Game_System zu kommen.


class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end

muss ich das auch noch irgendwie starten und wenn ja wo?

Kelven
30.04.2015, 21:23
Das ist seltsam, $game_system sollte es ja eigentlich schon geben. Die Fehlermeldung klingt im ersten Moment nämlich so, als ob $game_system noch nicht angelegt wurde, aber das sollte im laufenden Betrieb nicht der Fall sein. Oder benutzt du noch an anderer Stelle eine Variable oder Methode namens memory?

Elster
02.05.2015, 15:04
Ne, bin eben noch mal alle Scripte durchgegangen die ich verwende.
Nirgens findet sich auch nur das Wort "memory" oder "Memory"

Daher sollte es ja an und für sich auch keine Probleme mit anderen Scripten geben O_o (nicht in diesem Fall)
Falls es hilfreich ist, folgende Scripte sind noch im Einsatz. (Was euch ohne Code wenig hilft, aber irgendwie nehme ich auch mal an, dass ihr wenig Lust habt den durchzuschauen) ^^
...hätte ich auch nicht.



Yanfly Engine:
- Ace Message System
- Ace Menu Engine

Lone Wolf:
- Gamepad Extender

MOG
- MOG_Animated_Title_A

Khas Arcthunder:
- Pathfinding


Und dann halt noch eigene Scripte. Aber da bin ich mir recht sicher, dass da kein "Memory" oder "memory" drin vorhanden ist.
Bei den anderen auch... Suchfunktion und so.

Kelven
02.05.2015, 15:31
Kannst du vielleicht doch mal deine eigenen Scripte posten, also Game_Memory und Scene_Memory?

Elster
03.05.2015, 22:54
Also im Ganzen ist es halt das hier:



class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize
@figure_names = ["Spinne1.png", "Spinne2.png", "Spinne3.png", "Spinne4.png",
"Spinne5.png",
"Spinne6.png", "Spinne7.png", "Spinne8.png", "Spinne9.png", "Spinne10.png",
"Spinne11.png",
"Spinne12.png", "Spinne13.png", "Spinne14.png", "Spinne15.png", "Spinne16.png"]

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
0, 208,
136, 208,
272, 208,
408, 208,
#
0, 312,
136, 312,
272, 312,
408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 64
@card_height = 64
# distance between cards
@margin = 12
p @positions
#SceneManager.call(Scene_Memory.start)
#Scene_Memory.start
#SceneManager.call(Scene_Memory.start)
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end

class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base
#class << self
#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def initialize_graphics
# for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
end

def update_graphics
# update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics
end

def start #(start)
super
initialize_graphics
update
end

#b = Scene_Memory.new
#b.start

end
#end

#-------------------------------------------------------------------------------




#b = Scene_Memory.new
#b.start

Das ist momentan auskommentiert damit das Spiel startet und ich an anderen Sachen werkeln kann.

Kelven
03.05.2015, 23:34
In Game_System legst du noch gar keine Instanz von Game_Memory an, daher kommt wohl auch die Fehlermeldung. attr_accessor ermögtlich dir nur den Zugriff auf memory, sprich du kannst memory lesen und verändern. Angelegt wird memory dadurch noch nicht. Das ist zwar nicht die sauberste Art, aber du könntest ans Ende von initialize aus Game_System Folgendes setzen:

@memory = Game_Memory.new

Die Zeilen

#SceneManager.call(Scene_Memory.start)
#Scene_Memory.start
#SceneManager.call(Scene_Memory.start)

sind in der initialize-Methode von Game_Memory nicht so gut aufgehoben und syntaktisch denke ich auch nicht richtig. Auch

#b = Scene_Memory.new
#b.start

brauchst du nicht, weil der Scene_Manager das alles automatisch macht. Wenn ich den Ace richtig verstehe (ich kann mit der Lite-Version leider keine Scripts testen), dann müsstest du auf deiner ersten Map nur folgenden Aufruf machen:

Scene_Manager.call(Scene_Memory)

Falls ich etwas Falsches erzähle bitte gleich Bescheid sagen.

Elster
08.05.2015, 13:52
Ja, das geht... aber jetzt wird mein Stack zu groß XD
Wie kann ich das abfangen, dass mir nicht der Speicher ausgeht?

Kelven
08.05.2015, 14:52
Rufst du Scene_Manager.call(Scene_Memory) vielleicht mehrmals auf? Das muss du eigentlich nur einmal machen.

Elster
09.05.2015, 12:21
So weit ich es beurteilen kann nur einmal.
Halt in einem Event mit "Parallel Prozess" ein Skriptbefehl mit den beiden Befehlen:


$game_system.memory = Game_Memory.new
Scene_Manager.call(Scene_Memory)

und da drauner wird ein Selfswitch aktiviert. Dann eben eine Seite 2 die durch den Self-Switch aktiviert wird.
Zur Sicherheit hab ich auf Seite 1 unten auch noch ein "Clear Event" eingebaut... der Speicher wird aber auch so zu groß.
Ergo... daran kann es nicht liegen.

Cepanks
09.05.2015, 12:45
Hast du schon mal überprüft, ob das Script auch Probleme macht, wenn du es in ein neues Projekt ohne sonstige Scripte von anderen einfügst?

Ansonsten wäre es vielleicht auch sinnvoll, wenn du dein Projekt, oder zumindest Data/Scripts.rvdata2, irgendwo hochladen könntest, damit nicht tröpfchenweise Ferndiagnose stattfinden muss. ;)

-KD-
09.05.2015, 21:36
Ja, das geht... aber jetzt wird mein Stack zu groß XD
Wie kann ich das abfangen, dass mir nicht der Speicher ausgeht?

Du ruftst entweder innerhalb von Game_Memory ein Game_Memory.new auf oder innerhalb von Scene_Memory ein SceneManager.call(Scene_Memory). Das verursacht eine Endlosrekursion und dadurch den Stackoverflow.

Am besten du zeigst nochmal deinen Code so wie er jetzt aussieht.

Elster
11.05.2015, 13:12
Gut ja, dann liegt eindeutig hier der Fehler... gleich der letzte Befehl der Methode.



def initialize
@figure_names = ["Spinne1.png", "Spinne2.png", "Spinne3.png", "Spinne4.png",
"Spinne5.png",
"Spinne6.png", "Spinne7.png", "Spinne8.png", "Spinne9.png", "Spinne10.png",
"Spinne11.png",
"Spinne12.png", "Spinne13.png", "Spinne14.png", "Spinne15.png", "Spinne16.png"]

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
0, 208,
136, 208,
272, 208,
408, 208,
#
0, 312,
136, 312,
272, 312,
408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 64
@card_height = 64
# distance between cards
@margin = 12
p @positions

@memory = Game_Memory.new
end


Habe ich wohl etwas mal wieder falsch verstanden...

Ansonsten noch mal der ganze Code.


class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize
@figure_names = ["Spinne1.png", "Spinne2.png", "Spinne3.png", "Spinne4.png",
"Spinne5.png",
"Spinne6.png", "Spinne7.png", "Spinne8.png", "Spinne9.png", "Spinne10.png",
"Spinne11.png",
"Spinne12.png", "Spinne13.png", "Spinne14.png", "Spinne15.png", "Spinne16.png"]

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
0, 208,
136, 208,
272, 208,
408, 208,
#
0, 312,
136, 312,
272, 312,
408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 64
@card_height = 64
# distance between cards
@margin = 12
p @positions

@memory = Game_Memory.new
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end

class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base
#class << self
#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def initialize_graphics
# for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
end

def update_graphics
# update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics
end

def start #(start)
super
initialize_graphics
update
end

end
#end

Kelven
11.05.2015, 13:20
Ja und zwar passiert Folgendes: Eine neue Instanz von Game_Memory wird angelegt. Dabei wird initialize aufgerufen, doch Methode legt dann wegen dem Aufruf @memory = Game_Memory.new gleich nochmal eine weitere Instanz an und das unendlich lang. Der Aufruf sollte bei Game_System in die Initialize-Methode geschrieben werden und der Aufruf bei Game_Memory sollte wieder entfernt werden.

Normalerweise (falls du nicht schon etwas geändert hast, steht bei Game_System Folgendes:



#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
@save_disabled = false
@menu_disabled = false
@encounter_disabled = false
@formation_disabled = false
@battle_count = 0
@save_count = 0
@version_id = 0
@window_tone = nil
@battle_bgm = nil
@battle_end_me = nil
@saved_bgm = nil
end


Daraus machst du:



#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
@save_disabled = false
@menu_disabled = false
@encounter_disabled = false
@formation_disabled = false
@battle_count = 0
@save_count = 0
@version_id = 0
@window_tone = nil
@battle_bgm = nil
@battle_end_me = nil
@saved_bgm = nil

@memory = Game_Memory.new
end

Elster
02.06.2015, 15:32
Entschuldigt bitte das ich mir hier mit den Antworten so viel Zeit gelassen habe (RL und so).

Jedenfalls... ich habe nun die Sachen wie empfohlen geändert.
Nun habe ich jedoch wieder ein weiteres Problem.


Ich starte das Memory ja über die beiden Befehle hier:


$game_system.memory = Game_Memory.new
Scene_Manager.call(Scene_Memory)


Aus mir nun etwas unerfindlichen Gründen hat er nun wieder Probleme mit dem unteren Aufruf.
Das äußert sich mal wieder so...


Script 'GameInterpreter' line 1411: NameError occurred.
uninitialized constant Game_Interpreter::Scene_Manager


Wenn ich jetzt "Scene_Mager.call(Scene_Memory)" auskommentiere verschwindet der Fehler natürlich, aber ich bekomme halt auch keine Bilder angezeigt.

Linkey
02.06.2015, 19:47
Ohne jetzt deine Skripte anzuschauen, das Objekt heißt (ohne "_"): SceneManager

Versuch es mal damit (:

Elster
04.06.2015, 15:14
Oh man, manchmal hat man wirklich ein Brett vor dem Kopf :\

Dennoch, irgendwas scheint er wieder nicht finden zu wollen.


Script 'Cache' line 88: NoMethodError occurred.
undefined method `empty?' for nil:NilClass


Die Meldung taucht dann auf, wenn [card_x(index), card_y(index), card_image(index)] (Mathode get_card index) keine Werte mehr aus dem Koordinatenarray bekommt.
Nachdem der letzte Wert geschrieben wurde... zack Meldung.
Hab jedenfalls mal am Anfang jeder Methode mir eine "Ausgabe" machen lassen und mal die Consolenausgabe kopiert.
Der Länge wegen steht es halt in einem Spoiler, sonst erschlägt es einen.

"Game_system"
"Scene_Memory"
["Spinne1.png", "Spinne2.png", "Spinne3.png", "Spinne4.png", "Spinne5.png", "Spi
nne6.png", "Spinne7.png", "Spinne8.png"]
[0, 0, 136, 0, 272, 0, 408, 0, 0, 104, 136, 104, 272, 104, 408, 104, 0, 208, 136
, 208, 272, 208, 408, 208, 0, 312, 136, 312, 272, 312, 408, 312]
["Spinne1.png", "Spinne2.png", "Spinne3.png", "Spinne4.png", "Spinne5.png", "Spi
nne6.png", "Spinne7.png", "Spinne8.png"]
[0, 0, 136, 0, 272, 0, 408, 0, 0, 104, 136, 104, 272, 104, 408, 104, 0, 208, 136
, 208, 272, 208, 408, 208, 0, 312, 136, 312, 272, 312, 408, 312]
"start"
"initialize_graphics"
"get_cards"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"
"get_card index"
"card_x index"
"cary_y index"
"card_image index"

Rein theoretisch sollte es nun ja nach "get_cards" gehen .... an meine lieben Unterstützer, ich müsste hier vermutlich einen Aufruf von "get_card index" tätigen ... oder?

Linkey
04.06.2015, 15:43
Der Fehler wird erzeugt, da du die Cache.Picture mit nil aufrufst.
Dies geschieht durch deinen folgenden Code:

def card_image index
@figure_names[@positions[index]]
end

Ich vermute mal, du möchtest, je nach Index das figure_names Array ansprechen. Demnach sollte dein Code wie folgt lauten:

def card_image index
@figure_names[index]
end

Durch deinen aktuellen Code wird bpsw. bei Index = 3 nicht @figure_names[3] angesprochen (so wäre es beim unteren code), sondern @figure_names[136]. Dieser Wert ist im Array nicht vorhanden und daher nil.
(@positions[3] = 136)

Edit:
Desweiteren wird dein Code nicht funktionieren, da dein @positions 16 Koordinaten (je X und Y) beinhaltet, du aber nur 15 Grafiken in @figure_names gepflegt hast. Die 16. Koordinate wird daher auch "nil" als image wählen.

Elster
06.06.2015, 19:49
Okay, so weit geändert. Dennoch, der Fehler bleibt der selbe.
Durch ein wenig rumprobieren sind mir ein paar "Merkwürdigkeiten" aufgefallen, welche ich mir selber kaum erklären kann.
Erstmal habe ich mir mehr Sachen über die Konsole ausgeben lassen, so ist mir aufgefallen, dass bei den ganzen Koordinaten wirklich zu wenig Bilder (wie angemerkt) vorhanden waren. (irgendwann stand halt nil bei Werten drin, wie du bereits gesagt hast Likey)
Darüber hinaus ist mir aber was viel interessanteres ins Auge gefallen... so bald ich das Array @positions leer lasse, stürzt es nicht ab. So bald aber Werte drin stehen taucht halt der Fehler am Ende auf....
Ich könnte es mir so erklären das er halt mault weil bestimmte Werte nicht übereinstimmen... aber sicher bin ich mir da gerade wirklich nicht.

Mein momentaner Code:


class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize
@figure_names = ["Spinne1.png", "Spinne1.png",
"Spinne2.png", "Spinne2.png",
"Spinne3.png", "Spinne3.png",
"Spinne4.png", "Spinne4.png",
"Spinne5.png", "Spinne5.png",
"Spinne6.png", "Spinne6.png",
"Spinne7.png", "Spinne7.png",
"Spinne8.png", "Spinne8.png",
"Spinne9.png", "Spinne9.png",
"Spinne10.png", "Spinne10.png",
"Spinne11.png", "Spinne11.png",
"Spinne12.png", "Spinne12.png",
"Spinne13.png", "Spinne13.png",
"Spinne14.png", "Spinne14.png",
"Spinne15.png", "Spinne15.png",
"Spinne16.png", "Spinne16.png"
]

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
0, 208,
136, 208,
272, 208,
408, 208,
#
0, 312,
136, 312,
272, 312,
408, 312
]
# number of cards horizontal
@max_number_of_cols = 3
# size of cards
@card_width = 136
@card_height = 104
# distance between cards
@margin = 0
p @figure_names
p @positions

end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
p "get_card index"
[card_x(index), card_y(index), card_image(index)]
p card_x(index)
p card_y(index)
p card_image(index)
end

# return all cards
def get_cards
p "get_cards"
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
p "card_x index"
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
p "card_y index"
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
p "card_image index"
@figure_names[index]
#@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
p "number_of_pictures"
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
p "shuffle_cards"
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end

class Game_System
p "Game_system"
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base
p "Scene_Memory"
#class << self
#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def initialize_graphics
p "initialize_graphics"
# for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
end

def update_graphics
p "update_graphics"
# update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
p "dispose_grapics"
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
p "terminate"
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
p "update"
super
update_graphics
end

def start #(start)
p "start"
super
initialize_graphics
update
end

end
#end


Eine tollkühne Vermutung meinerseits ist, dass er mosert das die Koordinaten aus @positions momentan einfach nicht zu den Werten aus @card_width und @card_height passen... wobei ich da momentan wirklich keinen Grund für sehe.

Linkey
07.06.2015, 10:28
Hey Elster,
du hast dir deine Methode "def get_card index" selbst zerschossen. Du arbeitest in deinen Methoden ohne ein explizites "return" - was vollkommen okay ist. Allerdings solltest du dies nicht machen, da du ja scheinbar noch anfänger bist (was das Skripten mit Ruby angeht) und - wie man hier merkt - dir ein Eigentor geschossen hast.
Wenn du kein Return-Statement verwendest, gibt eine Methode in Ruby das letzte Statement zurück. In deinem Fall gibt die Methode also nicht mehr das Array zurück, sondern "p card_image(index)".
Wenn du die 3 Ausgaben also haben möchtest, musst du die über dein Array schreiben, damit das Array zurückgegeben wird:

def get_card index
p "get_card index"
p card_x(index)
p card_y(index)
p card_image(index)
[card_x(index), card_y(index), card_image(index)]
end



Edit:
Vielleicht erklärst du mal ganz genau, was du eigentlich vor hast. Irgendwie macht dein Code aktuell wenig Sinn. Was bezweckst du mit @positions eigentlich? Denn die Werte, die du in dem Array stehen hast, werden nie verwendet.

Elster
08.06.2015, 19:51
Es funktioniert tatsächlich ohne die Ausgaben.... yayi
Ich sehe Bilder <3

Mja was Ruby angeht bin ich echt ein absoluter Neuling...

Also was es einmal werden soll ist ein Memory. Wo man halt Paare von Karten finden soll. (soll dann noch auf sounds ausgeweitet werden, also zusätzlich ein Soundmemory.)
Das ist die Grundidee. Klar, dafür müssen vorher noch die Karten verdeckt sein/ werden.

Mein Gedankengang des Aufbaus war halt, dass man eben Koordinaten braucht um die Bilder zu plazieren, zudem IDs um die Paare ausfindig zu machen.
Das Skript stammt größtenteils von -KD- (danke noch einmal dafür :3) und darauf baue ich halt auf und wusel mich da halt durch.

In naher Zukunft folgt dann noch die Steuerung (Navigation über das Spielfeld) und Identifizierung der einzelnen Karten. Wie genau ich das mache weiß ich noch nicht.
Aber ich muss etwas zum "anklicken" haben, damit halt das Bild gezeigt wird oder ein Sound abgespielt wird, vielleicht geht es auch ohne Objekte auf der Map... hoffentlich.

Das Array benötige ich sicherlich später noch für die Steuerrung. Also dem Ansteuern eben jener Koordinaten um dann Dinge zu tun. [Bilder umdrehen, Sounds abspielen... oder was mir sonst so noch im Zusammenhang mit Anklicken einfällt]


Ich hoffe ich konnte mich hier halbwegs verständlich ausdrücken ^^" wenn ich mehr ins Detail gehen soll, kann ich das gerne tun.

Linkey
08.06.2015, 20:15
Alles klar. Ist ja super, dass es nun bis hierhin schon einmal funktioniert.

Aktuell berechnest du die Koordinaten ja komplett über die Methoden card_x und card_y.
In Zugriffen über @postions verwendest du lediglich den Index des Arrays, aber nie die Werte. Und wenn du später noch Dinge im Script einbaust, wirst du sicherlich auch hier die Methoden card_x und card_y verwenden (können).

Aber super, dass du dir Anhand der hier im Forum gegebene Unterstützung selbst an den Skripten versuchst.
Kannst dein fertiges Skript ja mal irgendwann vorstellen - ansonsten bis zum nächsten Problem~

Elster
25.06.2015, 12:59
Und da melde ich mich wieder ^^

Es sind ein paar neue Probleme aufgetaucht.
Das erste und größste Problem, ich weiß nicht wie ich gescheit meine beiden Klassen "Memory_Picture_Changer" und "Memory_Game_Navigate" starten soll.
Dadurch weiß ich natürlich auch noch nicht, ob das was ich mir gedacht habe so überhaupt funktioniert....

Auch habe ich noch eine Frage, kann man eigentlich ein Bild hier noch über die anderen Bilder legen?
Damit man z.B. einen Rahmen immer über eine Karte legen kann, oder einen Mauszeiger um zu sehen wo man eigentlich ist.


Wenn schon jemand Lust hat sich das "Grauen" anzuschauen, bitte schön XD


class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize

#Deckkarten
@figure_wrapper = [
"Grundkarte.png", "Grundkarte.png", #1
"Grundkarte.png", "Grundkarte.png", #2
"Grundkarte.png", "Grundkarte.png", #3
"Grundkarte.png", "Grundkarte.png", #4
"Grundkarte.png", "Grundkarte.png", #5
"Grundkarte.png", "Grundkarte.png", #6
"Grundkarte.png", "Grundkarte.png", #7
"Grundkarte.png", "Grundkarte.png", #8
]

#Bilderkarten
@figure_names = [
"Spinne1.png", "Spinne1.png",
"Spinne2.png", "Spinne2.png",
"Spinne3.png", "Spinne3.png",
"Spinne4.png", "Spinne4.png",
"Spinne5.png", "Spinne5.png",
"Spinne6.png", "Spinne6.png",
"Spinne7.png", "Spinne7.png",
"Spinne8.png", "Spinne8.png",
].shuffle

#Sounds für die Tonvariante
@sound_names = [
"Up1", "Up1", #1
"Thunder3", "Thunder3", #2
"Sword4", "Sword4", #3
"Switch2", "Switch2", #4
"Stare", "Stare", #5
"Shop", "Shop", #6
"Saint9", "Saint9", #7
"Miss", "Miss" #8
].shuffle

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
#0, 208,
#136, 208,
#272, 208,
#408, 208,
#
#0, 312,
#136, 312,
#272, 312,
#408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 136
@card_height = 104
# distance between cards
@margin = 0
# number of possible moves
@move = 32
# number of right pairs found. Win at 8
# change in def change_card for your game
@win = 0
p @figure_names
p @positions

end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
#@figure_names[index]
@figure_wrapper [index]
#@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
#p "number_of_pictures"
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
#p "shuffle_cards"
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end


class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base

def initialize_graphics
#for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
end

def update_graphics
#update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics
end

#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def start #(start)
super
initialize_graphics
update
end

end

#-------------------------------------------------------------------------------
# Hier findet das Verändern der Deckbilder statt.
# Ich sollte nach gleichen Namen schauen und wenn diese gleich sind, wird das
# Deckblatt entgültig entfernt.
#-------------------------------------------------------------------------------

class Memory_Picture_Changer

def initialize
@pic_ID1 = -1
@pic_ID2 = -2
p "wupi"
end


#Ändert die angezeigten Bilder.
# TODO Tonvariante einpflegen
def change_card

#zeigt die erste umgedeckte Karte an.
if @pic_ID1 != -1
a = @figure_names.select[@pic_ID1]
#ersetzen des Bildes an Stelle @pic_ID1 durch a
@figure_wrapper.map! {|x| x == @pic_ID1 ? a : x}.flatter
update_graphics()
end

#zeigt die zweite umgedeckte Karte an.
if @pic_ID2 != -2
b = @figure_names.select[@pic_ID2]
@figure_wrapper.map! {|y| y == @pic_ID1 ? b : y}.flatter
update_graphics()
end

if (@pic_ID1 != -1 && @pic_ID2 != -2)
#Wenn die Karten gleich sind!
if @pic1 == @pic2
Audio.se_play("Chime2", 80, 100)
@pic_ID1 = -1
@pic_ID2 = -2
@win +1
#Wenn die Karten ungleich sind!
else #(@pic1 != @pic2)
Audio.se_play("Buzzer2", 80, 100)
pic = "Grundkarte.png"
@figure_wrapper.map! {|x| x == @pic_ID1 ? pic : x}.flatter
@figure_wrapper.map! {|y| y == @pic_ID2 ? pic : y}.flatter
@pic_ID1 = -1
@pic_ID2 = -2
update_graphics()
end
end
end
end



# Hier findet die Navigation statt.
class Memory_Game_Navigate
def navigate
@x_nav = 0
@y_nav = 0
@id = 0

if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nax + 104
@id = @id + 4
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nax - 104
@id = @id - 4
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
end
end

if Input.trigger?(:C)
a = @figure_names.select[@id]
if a == "Grundkarte"
if @pic_ID1 == -1
@pic_ID1 = @id
$game_variables[10] = $game_variables[10] + 1
change_card()
elsif @pic_ID == -2
@pic_ID2 = @id
$game_variables[10] = $game_variables[10] + 1
change_card()
end
else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
Audio.se_play("Buzzer1", 80, 100)
end
$game_variables[10] = $game_variables[10] + 1
end

end
end

end

Linkey
25.06.2015, 14:03
Habe gerade nicht viel Zeit, daher antworte ich erst einmal nur auf die Teilfrage:



Auch habe ich noch eine Frage, kann man eigentlich ein Bild hier noch über die anderen Bilder legen?
Damit man z.B. einen Rahmen immer über eine Karte legen kann, oder einen Mauszeiger um zu sehen wo man eigentlich ist.


Das geht ganz einfach. Wenn dein Cursor z.B. ein Sprite/Window/Viewport ist, kannst du diesem einen höhreren "z"-Wert zuordnen und schon ist dieser über deinen anderen Bildern.
Wenn ich später zu Hause bin kann ich dir anhand deines Codes auch gerne ein Beispiel generieren.

Linkey
25.06.2015, 20:45
So, sorry für den Doppelpost. Ich habe mir dein Script gerade einmal angeschaut. Erst einmal als Anmerkung, du hast in der Navigate Klasse noch Schreibfehler. Schau mal in die Left/Right/Up/Down Methoden - dort steht teilweise @y_nax anstelle von @y_nav

Was deine Navigierungsklasse angeht, soll diese ja scheinbar für die Bewegungen zuständig sein. Ich würde dir empfehlen, hier eine init Methode anzulegen, in der du deinen Cursor-Sprite definierst (wenn du es ganz hart trenenn willst, kannst du den Cursor-Sprite natürlich auch in der Scene-Klasse mit anlegen und dir nur die x/y Werte über die Navigate-Klasse holen). Auf jeden Fall solltest du die x/y-Werte in der Init Methode initialisieren und nicht in "navigate". Denn sonst schreibst du die Werte immer auf 0. In den einzelnen Tastenabfragen rufst du dann zum Schluss eine Methode auf, die die Cursor Postion = x/y_nav setzt (siehe blaue Markierung).
Außerdem kannst du aus deinen Methoden die "Fehlerbehandlung" in eine eigene Methode auslagern (siehe grüne Markierungen).

Zu den roten Markierungen schreib ich dir weiter unten noch etwas.

Die Navigate-Klasse wäre dann bspw. so angepasst:



class Memory_Game_Navigate
def initialize
@cursor = Sprite.new
@cursor.z = 500 #Kommentar: Die meisten Sprites liegen im Z-Wert zwischen 0 und 300. Mit 500 solltest du auf jeden Fall auf der obersten Ebene sein, wodurch dein Cursor über allem steht.
@cursor.bitmap = Cache.picture("XXXXXXXXXXX.PNG")
@x_nav = 0
@y_nav = 0
@id = 0
end

def navigate
if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
move_error
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nav + 104
@id = @id + 4
move_cursor
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
move_error
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
move_cursor
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
move_error
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nav - 104
@id = @id - 4
move_cursor
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
move_error
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
move_cursor
end
end

if Input.trigger?(:C)
a = @figure_names.select[@id]
if a == "Grundkarte"
if @pic_ID1 == -1
@pic_ID1 = @id
$game_variables[10] = $game_variables[10] + 1
change_card()
elsif @pic_ID == -2
@pic_ID2 = @id
$game_variables[10] = $game_variables[10] + 1
change_card()
end
else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
Audio.se_play("Buzzer1", 80, 100)
end
$game_variables[10] = $game_variables[10] + 1
end

end

end

def move_cursor
@cursor.x = @x_nav
@cursor.y = @y_nav
end

def move_error
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
end
end



Die Klasse Memory_Game_Navigate muss dann als Objekt in deiner Scene erstellt werden (bspw. so in der init-Methode):


class Scene_Memory < Scene_Base

def initialize_graphics
#for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
@navi = Memory_Game_Navigate.new
end


Damit die Methode navigate der Klasse Memory_Game_Navigate auch ständig durchlaufen (und somit abgefragt wird), solltest du diese in der Update-Methode deiner Scene verwenden:


#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics
@navi.navigate
end


Bezüglich der roten Markierung weiter oben:
Du versuchst viele Klassen zu verwenden - toll. Allerdings muss dir bewusst sein, dass du nicht Klassen übergreifend irgendwelche Attribute/Methoden einfach so zur Verfügung gestellt hast. Du versuchst in deiner navigate-Methode der Navigations-Klasse z.B. auf die "change_card()"-Methode zuzugreifen. Diese ist der Klasse aber nicht bekannt. Du müsstest dann schon ein Objekt der "Change" Klasse erzeugen (@pic_changer = Memory_Picture_Changer.new), und dann über das Objekt auf die Methoden zugreifen (@pic_changer.change_card()).
Da du allerdings in der Memory_Picture_Changer Klasse auch wiederum Objekte der Memory-Klasse verwendest, die allerdings nur der Memory-Klasse bei dir bekannt sind, würde das auch nicht laufen. Du müsstest dann auf den "figure_wrapper" per $game_system.memory.figure_wrapper zugreifen und diesen vorher auch noch als attribute accessor in deiner Memory-Klasse definieren.

Elster
28.06.2015, 14:03
YAYI Danke ^^
Der Mauszeiger funktioniert wunderbar ^_^

Nur habe ich jetzt ein weiteres Problem.
Die Arrays liegen in einer privaten Methode... wie komme ich denn jetzt da an die Bilder?^^"
Habs ja erst versucht indem ich dafür auch ein neues Objekt der Klasse angelegt habe und dann auf die Methode zugreife... aber ist halt unzulässig.

Linkey
28.06.2015, 14:17
Zeig mal, was du versucht hast.
Deine Arrays liegen ja eigentlich nicht in einer privaten Methode, sondern als Instanz-Variablen deiner Klasse vor. Du kannst...
... der Klasse eine Methode hinzufügen, welche die Arrays ausgibt (lesender Zugriff) oder eine Methode mit Parameter hinzufügen, welche das Array dann verändert (schreibender Zugriff). In dem Fall könntest du dann per $game_system.memory.METHODEN_NAME(PARAMETER) auf die Methode zugreifen.
... die Arrays als Attribut-Reader (falls nur lesender Zugriff benötigt wird) oder Attribut-Accessor (falls auch schreiben drauf zugegriffen werden muss) deklarieren. In dem Falle könntest du dann per $game_system.memory.ARRAY_NAME auf das Objekt zugreifen.

Elster
28.06.2015, 15:17
Also ich habe es jetzt mal wie folgt versucht:

Folgende Methode habe ich unter der Klasse "Game_Memory" und unter der Methode "initialize"
Ich hoffe mal... dass das so funktioniert. (anscheinend nicht... wie du unten sehen wirst bei der Fehlermeldung)



def get_arrays
@wrapper = @figure_wrapper
@names = @figure_names
@sounds = @sound_names
end


So... hier hakt es dann halt.
Wo es rot makiert ist.



def navigate
@pic_changer = Memory_Picture_Changer.new
@get_id = Game_Memory.new
@h = $game_system.memory.get_arrays(@wrapper)
#@h = $game_system.memory.initialize(@figure_wrapper)

if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nav + 104
@id = @id + 4
move_cursor()
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
move_error()
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
move_cursor()
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nav - 104
@id = @id - 4
move_cursor()
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
move_error()
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
move_cursor()
end
end

if Input.trigger?(:C)
a = @figure_names.select[@id]
if a == "Grundkarte"
if @pic_ID1 == -1
@pic_ID1 = @id
$game_variables[10] = $game_variables[10] + 1
@pic_changer.change_card()
#change_card()
elsif @pic_ID == -2
@pic_ID2 = @id
$game_variables[10] = $game_variables[10] + 1
@pic_changer.change_card()
#change_card()
end
else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
Audio.se_play("Buzzer1", 80, 100)
end
$game_variables[10] = $game_variables[10] + 1
end

end

end




Script 'Memory_3' line 353: ArgumentError occurred.
wrong number of arguments (1 for 0)


Vermutlich habe ich nicht wirklich verstanden was du mir eben geschrieben hast ._.

Cepanks
28.06.2015, 16:49
Scheint, als hättest du die Teile aus Linkeys Antwort irgendwie zusammengemixt. :D

Vergleiche mal, wie du die Methode geschrieben hast, und wie du sie aufrufen willst. Es wird versucht @wrapper als Parameter zu übergeben, die Methode akzeptiert aber gar keine Parameter. Du willst an dieser Stelle aber nichts überschreiben (was denn auch?) oder sonst was tun, wofür ein Wert aus nötig wäre. Also weg damit.


@h = $game_system.memory.get_arrays


Nächste Baustelle:


def get_arrays
@wrapper = @figure_wrapper
@names = @figure_names
@sounds = @sound_names
end

Was passiert hier? So wie du es geschrieben hast, besitzt jetzt jetzt Game_Memory die Instanzvariablen @wrapper, @names, @sound, @figure_wrapper, @figure_names, @sound_names. Macht keinen Sinn, oder? Du willst die Sachen ja von außerhalb nutzen, jetzt haben wir hingegen die Arrays in doppelter Ausführung in Game_Memory.

Weil Ruby aber immer den letzten Wert aus einer Methode zurück gibt, hat es tatsächlich auch was in deine @h-Variable geschafft. Die würde jetzt das Array mit den Sound-Namen enthalten, allerdings auch nur dieses eine Array.

Wenn du alle drei haben willst, kannst du die Methode so umschreiben, dass sie ein "Array mit Arrays" liefert.


def get_arrays
# Das "return" ist wie gesagt optional
return [@figure_wrapper, @figure_names, @sound_names]
end


Dann die andere Variante, die Linkey vorgschlagen hat. Wenn du dir schon mal die anderen Klassen im Maker angesehen hast, bist du da bestimmt schon darüber gestolpert. Damit kannst du den Zugriff auf Instanzvariablen nach außen hin erlauben, ohne explizit Methoden dafür zu schreiben.

Entweder nur lesbar: attr_reader :figure_wrapper, :figure_names, :sound_names

nur schreibbar: attr_writer :figure_wrapper, :figure_names, :sound_names (macht in deinem Fall gerade keinen Sinn)

Oder les- und schreibbar: attr_accessor :figure_wrapper, :figure_names, :sound_names

Schau mal in Game_Memory in die 4. Zeile, auf @figure_names ist sogar schon zugreifbar.



Das Endergebnis sollte also so aussehen.


### Variante mit der geänderten get_array-Methode
def navigate
# Sieht auf den ersten Blick seltsam aus, aber wir ziehen hier die drei Werte aus dem zurückggebenen Array direkt in drei Instanzvariablen
@figure_wrapper, @figure_names, @sound_names = $game_system.memory.get_arrays
end


### Variante mit attr_reader oder attr_accessor
def navigate
@figure_wrapper = $game_system.memory.figure_wrapper
@figure_names = $game_system.memory.figure_names
@sound_names = $game_system.memory.sound_names
end

Linkey
28.06.2015, 16:51
Ja, so kann es nicht funktionieren.
Du rufst die Methode "get_arrays" von $game_system.memory auf (eine Instanz von Game_Memory), was erst einmal okay ist.

Wenn du dir die Methode "get_array" aber einmal anschaust, so hat diese keine Parameter. Du versucht den Aufruf aber mit einer Parameterübergabe (@wrapper) durchzuführen. Dies kann nicht funktionieren, da "get_array" kein Parameter vorsieht. Daher der Fehler "wrong number of arguments" - welcher aussagt, dass du zuviele oder zuwenige Parameter übergeben hast.
Deine Methode würde aber auch nicht das geben, was du willst. Deine Methode hat kein "return"-Statement. Deshalb würde der letzte Wert zurückgegeben werden. D.h. in deinem Fall, dass dein @h das Ergebnis von "
@sounds = @sound_names" zugewiesen bekommt. Du könntest die Methode wiefolgt schreiben:



def get_arrays
return @figure_wrapper, @figure_names, @sound_names
end

In deine andere Methode, die diese Werte erhalten soll, schreibst du dann anstelle von "@h = ..." (namen der variablen sind nur beispiele:

f_wrapper, f_names, s_names = $game_system.memory.get_arrays()

Edit:
Ach, 1-2 Minuten zu langsam. Hätte ich mal nicht gegessen xP

Edit 2:
Da hat Gepanks dir das noch einmal ausführlich erklärt. Nur der Vollständigkeit wegen:
Wie Gepanks schon sagt, kannst du das return statement weglassen (warum du es nicht machen solltest, habe ich ja bereits erwähnt und anhand deiner Fehler hast du ja auch gemerkt, was durch dieses Weglassen alles schiefgehen kann :) ). Du könntest die Klammern beim Return auch weglassen, Ruby gibt die Werte automatisch als Array zurück, wenn diese durch Komma getrennt angegeben sind.
Solltest du die Werte auch nur in der Methode "navigate" benötigen, brauchst du auch nicht unbedingt Instanzvariablen (bspw.: @figure_names = $game_system.memory.figure_names), sondern kannst einfache temporäre Variablen nehmen (bspw.: figure_names = $game_system.memory.figure_names).

Wie gesagt, es empfiehlt sich, gerade am Anfang, das Coding so zu schreiben, dass du auch nicht den Überblick verlierst. Daher solltest du den Code nur dort vereinfach schreiben, wo du dir auch sicher bist, was du da machst :)

Elster
29.06.2015, 20:00
Arg... langsam bekomme ich Kopfschmerzen.

Ich versuche gerade mein Konstrukt im Kopf zu entwirren...
Also jetzt wo ich da alles so schön bei sammen habe, rufe ich ja die Klasse "Memory_Picture_Changer" auf, um dort eben die Bilder zu aktualisieren. Leider habe ich dort weder die Namen noch die IDs zur Verfügung welche ich mitlerweile in der Klasse "Memory_Game_Navigate" relativ einfach herraussuchen kann. Wäre es nicht an und für sich logischer das in einem Rutsch zu erledigen, oder ist es besser das in verschiedenen Klassen zu lassen?
So wie ich es nun gedacht habe, also mit getrennten Klassen, stolpere ich wiedermal darüber, dass ich an Werte von Variablen rankommen muss (@pic_ID1 und @pic_ID2). Um dann die Werte der beiden Variablen wieder auf -1 und -2 zu setzen wenn ich kein Paar gefunden habe und sie an "Memory_Game_Navigate" senden muss. (für mich als Anfänger klingt das nach viel böser Arbeit...)
Hinzukommt... das ich eh "update_graphics()" aufrufe um mein Array zu aktualisieren, wobei ich mich da auch gerade frage... arbeite ich da überhaupt auf dem "richtigen" Array? So wie ich das bis jetzt verstanden habe, würde das Array der Methode nicht die Bohne verstehen was ich eigentlich von ihm will und einfach das ausgeben, was es eh schon die ganze Zeit über hatte, unverändert versteht sich.


Ich hab ja auch mit dem Gedanken gespielt einfach "Memory_Picture_Changer" von "Memory_Game_Navigate" erben zu lassen, dann sollte ich ja an die aktuellen Werte rankommen.... dachte ich. Hilft mir leider auch nicht dabei weiter, wie ich "Memory_Game_Navigate" sage, dass die beiden Variablen nun wieder ihre Ursprungswerte haben.

Kann jemand meinen armen Kopf entwirren?

Momentan sieht das Ganze wie folgt aus:
(Klar, das wirft noch Fehler wenn man was anklickt, weil Variablen in der Klasse "Memory_Picture_Changer" fehlen.)


class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize

#Deckkarten
@figure_wrapper = [
"Grundkarte.png", "Grundkarte.png", #1
"Grundkarte.png", "Grundkarte.png", #2
"Grundkarte.png", "Grundkarte.png", #3
"Grundkarte.png", "Grundkarte.png", #4
"Grundkarte.png", "Grundkarte.png", #5
"Grundkarte.png", "Grundkarte.png", #6
"Grundkarte.png", "Grundkarte.png", #7
"Grundkarte.png", "Grundkarte.png", #8
]

#Bilderkarten
@figure_names = [
"Spinne1.png", "Spinne1.png",
"Spinne2.png", "Spinne2.png",
"Spinne3.png", "Spinne3.png",
"Spinne4.png", "Spinne4.png",
"Spinne5.png", "Spinne5.png",
"Spinne6.png", "Spinne6.png",
"Spinne7.png", "Spinne7.png",
"Spinne8.png", "Spinne8.png",
].shuffle

#Sounds für die Tonvariante
@sound_names = [
"Up1", "Up1", #1
"Thunder3", "Thunder3", #2
"Sword4", "Sword4", #3
"Switch2", "Switch2", #4
"Stare", "Stare", #5
"Shop", "Shop", #6
"Saint9", "Saint9", #7
"Miss", "Miss" #8
].shuffle

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
#0, 208,
#136, 208,
#272, 208,
#408, 208,
#
#0, 312,
#136, 312,
#272, 312,
#408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 136
@card_height = 104
# distance between cards
@margin = 0
# number of possible moves
@move = 32
# number of right pairs found. Win at 8
# change in def change_card for your game
@win = 0
#p @figure_names
#p @positions

end

def get_arrays
return @figure_wrapper, @figure_names, @sound_names
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
#@figure_names[index]
@figure_wrapper [index]
#@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
#p "number_of_pictures"
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
#p "shuffle_cards"
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end


class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base

def initialize_graphics
#for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
@navi = Memory_Game_Navigate.new
end

def update_graphics
#update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics
@navi.navigate
end

#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def start #(start)
super
initialize_graphics
update
end

end

#-------------------------------------------------------------------------------
# Hier findet das Verändern der Deckbilder statt.
# Ich sollte nach gleichen Namen schauen und wenn diese gleich sind, wird das
# Deckblatt entgültig entfernt.
#-------------------------------------------------------------------------------

class Memory_Picture_Changer

#def initialize
#@navigater = Memory_Game_Navigate.new
#@pic_ID1 = -1
#@pic_ID2 = -2
#end


#Ändert die angezeigten Bilder.
# TODO Tonvariante einpflegen
def change_card
#@navigater = Memory_Game_Navigate.new
#f_wrapper, f_names, s_names = $game_system.memory.get_arrays()

#zeigt die erste umgedeckte Karte an.
if @pic_ID1 != -1
@c = f_names[@pic_ID1]
#@figure_wrapper.map! {|x| x == @pic_ID1 ? a : x}.flatter
@f_wrapper.map! {|x| x == @pic_ID1 ? @c : x}.flatter
update_graphics()
end

#zeigt die zweite umgedeckte Karte an.
if @pic_ID2 != -2
@d = f_names[@pic_ID2]
@f_wrapper.map! {|x| x == @pic_ID1 ? @d : x}.flatter
#@figure_wrapper.map! {|y| y == @pic_ID1 ? b : y}.flatter
update_graphics()
end

if (@pic_ID1 != -1 && @pic_ID2 != -2)
#Wenn die Karten gleich sind!
if @pic1 == @pic2
Audio.se_play("Chime2", 80, 100)
@pic_ID1 = -1
@pic_ID2 = -2
@win +1
#Wenn die Karten ungleich sind!
else #(@pic1 != @pic2)
Audio.se_play("Buzzer2", 80, 100)
pic = "Grundkarte.png"
@f_wrapper.map! {|x| x == @pic_ID1 ? pic : x}.flatter
@f_wrapper.map! {|y| y == @pic_ID2 ? pic : x}.flatter
#@figure_wrapper.map! {|x| x == @pic_ID1 ? pic : x}.flatter
#@figure_wrapper.map! {|y| y == @pic_ID2 ? pic : y}.flatter
@pic_ID1 = -1
@pic_ID2 = -2
update_graphics()
end
end
end


end



# Hier findet die Navigation statt.
class Memory_Game_Navigate

def initialize
@cursor = Sprite.new
#Kommentar: Die meisten Sprites liegen im Z-Wert zwischen 0 und 300.
#Mit 500 solltest du auf jeden Fall auf der obersten Ebene sein, wodurch
#dein Cursor über allem steht.
@cursor.z = 500
@cursor.bitmap = Cache.picture("Zeiger.PNG")
@x_nav = 0
@y_nav = 0
@id = 0
@pic_ID1 = -1
@pic_ID2 = -2
@win = 0
end


def navigate
@pic_changer = Memory_Picture_Changer.new
@get_id = Game_Memory.new
# f_wrapper enthält die Deckblätter
# f_names enthält die Bilder
# s_names enthält die Sounds
f_wrapper, f_names, s_names = $game_system.memory.get_arrays()
#p f_names
#@h = $game_system.memory.initialize(@figure_wrapper)

if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nav + 104
@id = @id + 4
move_cursor()
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
move_error()
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
move_cursor()
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nav - 104
@id = @id - 4
move_cursor()
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
move_error()
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
move_cursor()
end
end

if Input.trigger?(:C)
a = f_names[@id]
b = f_wrapper[@id]
#a = @figure_names.select[@id]
if b == "Grundkarte.png"
if @pic_ID1 == -1
$game_variables[10] = $game_variables[10] + 1
@pic_ID1 = @id
@pic_changer.change_card()
#change_card()
elsif @pic_ID2 == -2
$game_variables[10] = $game_variables[10] + 1
@pic_ID2 = @id
@pic_changer.change_card()
#change_card()
end
else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
Audio.se_play("Buzzer1", 80, 100)
end
$game_variables[10] = $game_variables[10] + 1
end

end

end

#Hier findet die Bewegung des Mauszeigers statt.
def move_cursor
@cursor.x = @x_nav
@cursor.y = @y_nav
end

#hier wird der Ton abegespielt wenn sich der Spieler nicht mehr bewegen kann.
def move_error
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
end

end

Linkey
29.06.2015, 20:20
Bin gerade nicht so fit, deshalb habe ich deinen Text nur kurz überflogen. Ich hoffe, ich habe es richtig gelesen.
Die @pic-Variablen setzt du zwar in der Navigate Klasse, brauchst die dort aber praktisch gar nicht, wenn ich das richtig überflogen habe.
Wie wäre es, wenn du die ID einfach übergibst? Du könntest deine "change_card"-Methode anpassen:




def change_card(pID1,pID2)
#@navigater = Memory_Game_Navigate.new
#f_wrapper, f_names, s_names = $game_system.memory.get_arrays()

#zeigt die erste umgedeckte Karte an.
if pID1 != -1
@c = f_names[pID1]
#@figure_wrapper.map! {|x| x == pID1 ? a : x}.flatter
@f_wrapper.map! {|x| x == pID1 ? @c : x}.flatter
update_graphics()
end

#zeigt die zweite umgedeckte Karte an.
if pID2 != -2
@d = f_names[pID2]
@f_wrapper.map! {|x| x == pID1 ? @d : x}.flatter
#@figure_wrapper.map! {|y| y == pID1 ? b : y}.flatter
update_graphics()
end

if (pID1 != -1 && pID2 != -2)
#Wenn die Karten gleich sind!
if pID1 == pID2
Audio.se_play("Chime2", 80, 100)
pID1 = -1
pID2 = -2
@win +1
#Wenn die Karten ungleich sind!
else #(pID1 != pID2)
Audio.se_play("Buzzer2", 80, 100)
pic = "Grundkarte.png"
@f_wrapper.map! {|x| x == pID1 ? pic : x}.flatter
@f_wrapper.map! {|y| y == pID2 ? pic : x}.flatter
#@figure_wrapper.map! {|x| x == @pic_ID1 ? pic : x}.flatter
#@figure_wrapper.map! {|y| y == @pic_ID2 ? pic : y}.flatter
pID1 = -1
pID2 = -2
update_graphics()

end
end
return pID1,pID2
end



Die Methode rufst du dann in deiner Navigate-Klasse so auf:


@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)


Edit:
Bezüglich der Klassen:
Du kannst tatsächlich auf weniger Klassen zugreifen. Generell ist es ein guter Gedanke, Dinge in einzelne Klassen zu packen. Der Maker macht es ja auch so:
Für einzelne Ausgaben gibt es Window_Klassen. Für die Steuerung über diese Menüs dann die Scene_Klassen.

Wenn du allerdings an einen Punkt kommst, an dem du nicht mehr weiter kommst, du permanent Werte hin- und herschieben musst und jegliche Übersicht verlierst, solltest du vielleicht ein bisschen weniger auslagern.

Elster
30.06.2015, 09:26
Hm ne, ich denke nicht dass das so geht.
Ich habe dann ja am Anfang der Methode (pID1 und pID2) in denen "nil" drin steht, wodurch das Programm abschmieren wird. (Habe es auch ausprobiert, dass Programm schmiert ab)

Zudem hast du recht, ich brauche in meiner "Memory_Game_Navigate" Klasse die pic_ID1 und pic_ID2 nicht, ermittel sie jedoch dort um sie an "Memory_Picture_Changer" zu senden um dort mit den Werten arbeiten zu können.
Ergo... müsste ich dann nicht auch einen Aufruf aller:

@pID1,@pid2 = @naviagter.navigate(@pic_ID1, pic_ID2)
machen, damit ich mit den aktuellen Werten in "Memory_Picture_Changer" arbeiten kann?
Weil ich brauche ja dort die Werte.

Edit:
hum, er schmiert ab... unschön. "wrong number of arguments" ... habs mir wohl leichter gedacht als es ist....

Edit2:
Gut, hätte es mir denken können, ich arbeite ja nun nur mit "nil"... weil ja nirgends irgendwo etwas drin steht. Bedeutet, ich müsste es einmal mit den -Werten in Navigate anlegen und mir dann eine Variable anlegen, die ich erhöhe wenn ich Werte in pic_ID1 und pic_ID2 stehen habe.
Dann arbeite ich mit einer if-Abrage um mir am Anfang die Minuswerte wieder zu holen... und setze die Variable wieder auf 0 oder so...
Irgendwie kommt es mir so vor als hätte ich noch einen Denkfehler darin.

Linkey
30.06.2015, 11:43
Sicher, dass es nicht ging? In der Intial-Methode hast du @pic_ID1 und @pic_ID2 auf Minuswerte gesetzt (hier dein Code):


def initialize @cursor = Sprite.new
#Kommentar: Die meisten Sprites liegen im Z-Wert zwischen 0 und 300.
#Mit 500 solltest du auf jeden Fall auf der obersten Ebene sein, wodurch
#dein Cursor über allem steht.
@cursor.z = 500
@cursor.bitmap = Cache.picture("Zeiger.PNG")
@x_nav = 0
@y_nav = 0
@id = 0
@pic_ID1 = -1
@pic_ID2 = -2
@win = 0
end

Dadurch sind die Variablen ja erst einmal gesetzt.

Nun rufst du die Changer-Methode "change_card" auf, und übergibst ja die IDs. Dementsprechend sind diese Variablen nicht nil. Sicher, dass es dewesegen abgeschmiert ist? Wenn ich mir deinen Code anschaue, sind dort einige andere Fehler drin, die das Programm zum Abschmieren bringen können (update_graphics() rufst du im change_card auf, obwohl diese Methode gar nicht der Klasse Pic_Changer bekannt ist....).

Welche Fehlermeldung hast du erhalten, als du versucht hast die Werte zu übergeben? Gib mir mal den Code davon, dann schaue ich mir das heute nach der Arbeit mal an.

Edit:
Noch einmal kurz als Erklärung. Du ermittelst in Klasse A die Variablen ID1 und ID2 und brauchst diese in Klasse B. Wenn du von Klasse A aus die Klasse B aufrufst (in deinem Fall die MEthode change_pic), macht es dann sinn, die Variablen an dieser Stelle zu übergeben. Daher rufst du von deiner Klasse aus die "change_pic" Methode mit den Variablen auf (change_pic(ID1,ID2)). Und nicht umgekehrt.

Elster
02.07.2015, 14:44
Ja, kann natürlich auch daran liegen. Wirds wohl.

Zu dem Aufruf. Sollte der dann nicht eigentlich so aussehen?

@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pID1,@pID2)

Weil change_card gibt ja @pID1 und pID2 zurück, oder sind die Bezeichner der Variablen in so fern irrelevant und Ruby weiß schon was es tun soll?

Wobei ich andere Fehler je nach Variante bekomme...
Wenn ich [@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)] nutze, dann bleibt oben links in der Ecke mein Mauszeiger kleben... zumindest Einer. Einen anderen kann ich munter über die Karten bewegen.
Klicke ich dann etwas an, findet er in Zeile 423 einen Fehler (Wrong number of arguments (0 for 2)).
Das wäre dann der Befehl "@pic_changer.change_card()" in der Methode "def navigate".

Wenn ich [@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pID1,@pID2)] nutze, dann bekomme ich eine mja... gravierendere Fehlermeldung.
"line288 type error occurred. no implicit conversion from nil to integer".
Dabei handelt es sich dann um die Zeile "@c = f_names[pID1]" aus der Methode "change_card". Kann natürlich mit einem vorher falsch ausgeführten Befehl zusammen hängen.

Momentan sieht der Code wie folgt aus:


class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize

#Deckkarten
@figure_wrapper = [
"Grundkarte.png", "Grundkarte.png", #1
"Grundkarte.png", "Grundkarte.png", #2
"Grundkarte.png", "Grundkarte.png", #3
"Grundkarte.png", "Grundkarte.png", #4
"Grundkarte.png", "Grundkarte.png", #5
"Grundkarte.png", "Grundkarte.png", #6
"Grundkarte.png", "Grundkarte.png", #7
"Grundkarte.png", "Grundkarte.png", #8
]

#Bilderkarten
@figure_names = [
"Spinne1.png", "Spinne1.png",
"Spinne2.png", "Spinne2.png",
"Spinne3.png", "Spinne3.png",
"Spinne4.png", "Spinne4.png",
"Spinne5.png", "Spinne5.png",
"Spinne6.png", "Spinne6.png",
"Spinne7.png", "Spinne7.png",
"Spinne8.png", "Spinne8.png",
].shuffle

#Sounds für die Tonvariante
@sound_names = [
"Up1", "Up1", #1
"Thunder3", "Thunder3", #2
"Sword4", "Sword4", #3
"Switch2", "Switch2", #4
"Stare", "Stare", #5
"Shop", "Shop", #6
"Saint9", "Saint9", #7
"Miss", "Miss" #8
].shuffle

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
#0, 208,
#136, 208,
#272, 208,
#408, 208,
#
#0, 312,
#136, 312,
#272, 312,
#408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 136
@card_height = 104
# distance between cards
@margin = 0
# number of possible moves
@move = 32
# number of right pairs found. Win at 8
# change in def change_card for your game
@win = 0
#p @figure_names
#p @positions

end

def get_arrays
return @figure_wrapper, @figure_names, @sound_names
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
#@figure_names[index]
@figure_wrapper [index]
#@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
#p "number_of_pictures"
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
#p "shuffle_cards"
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end


class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base

def initialize_graphics
#for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
@navi = Memory_Game_Navigate.new
end

def update_graphics
#update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics
@navi.navigate
end

#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def start #(start)
super
initialize_graphics
update
end

end

#-------------------------------------------------------------------------------
# Hier findet das Verändern der Deckbilder statt.
# Ich sollte nach gleichen Namen schauen und wenn diese gleich sind, wird das
# Deckblatt entgültig entfernt.
#-------------------------------------------------------------------------------

class Memory_Picture_Changer

#def initialize
#@navigater = Memory_Game_Navigate.new
#@pic_ID1 = -1
#@pic_ID2 = -2
#end


#Ändert die angezeigten Bilder.
# TODO Tonvariante einpflegen
def change_card(pID1,pID2)
@navigater = Memory_Game_Navigate.new
@memo = Game_Memory.new
f_wrapper, f_names, s_names = $game_system.memory.get_arrays()
#@pID1,@pid2 = @naviagter.navigate(@pic_ID1, pic_ID2)
#pID1 = -1
#pID2 = -2

#zeigt die erste umgedeckte Karte an.
if pID1 != -1
@c = f_names[pID1]
@f_wrapper.map! {|x| x == pID1 ? @c : x}.flatter
memo.update_graphics()
end

#zeigt die zweite umgedeckte Karte an.
if pID2 != -2
@d = f_names[pID2]
@f_wrapper.map! {|x| x == pID1 ? @d : x}.flatter
memo.update_graphics()
end

if (pID1 != -1 && pID2 != -2)
#Wenn die Karten gleich sind!
if pID1 == pID2
Audio.se_play("Chime2", 80, 100)
pID1 = -1
pID2 = -2
@win +1
#Wenn die Karten ungleich sind!
else #(pID1 != pID2)
Audio.se_play("Buzzer2", 80, 100)
pic = "Grundkarte.png"
@f_wrapper.map! {|x| x == pID1 ? pic : x}.flatter
@f_wrapper.map! {|y| y == pID2 ? pic : x}.flatter
pID1 = -1
pID2 = -2
memo.update_graphics()
end
end
return pID1,pID2
end


#also, ich muss irgendwie die Variablen da oben nutzen um da die Namen der
#der Karten reinzuschreiben. Mit der ID arbeite ich dann um die Karten
#zu zeigen oder wieder das Deckblatt draufzulegen.
#ergo brauche ich noch ID Variablen.
#dann muss ich noch an die IDs der Karten kommen. Das müsste ich wohl über
#die Bewegung machen... die irgendwie weiter zählt. Geht man nach rechts
#halt + auf der x-Achse, geht man nach links - auf der x-Achse
#geht man nach oben - auf der y-Achse geht man nach unten + auf der y-Achse
#irgendwie muss ich den Spaß dann auch noch starten und symbolisieren
#wie man sich bewegt, ich würde ja gerne einen roten Rahmen um das Bild
#legen der dann da einfach auf dem aktuellen Standort auftaucht, nur wie?
#erstmal muss ich eh herausfinden wie ich Elemente in einem Array an einer
#bestimmten Stelle verändere.
end



# Hier findet die Navigation statt.
class Memory_Game_Navigate

def initialize
@cursor = Sprite.new
#Kommentar: Die meisten Sprites liegen im Z-Wert zwischen 0 und 300.
#Mit 500 solltest du auf jeden Fall auf der obersten Ebene sein, wodurch
#dein Cursor über allem steht.
@cursor.z = 500
@cursor.bitmap = Cache.picture("Zeiger.PNG")
@x_nav = 0
@y_nav = 0
@id = 0
@pic_ID1 = -1
@pic_ID2 = -2
@win = 0
end


def navigate
@pic_changer = Memory_Picture_Changer.new
@get_id = Game_Memory.new
# f_wrapper enthält die Deckblätter
# f_names enthält die Bilder
# s_names enthält die Sounds
f_wrapper, f_names, s_names = $game_system.memory.get_arrays()
#@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pID1,@pID2)
#@h = $game_system.memory.initialize(@figure_wrapper)

if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nav + 104
@id = @id + 4
move_cursor()
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
move_error()
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
move_cursor()
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nav - 104
@id = @id - 4
move_cursor()
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
move_error()
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
move_cursor()
end
end

if Input.trigger?(:C)
a = f_names[@id]
b = f_wrapper[@id]
#a = @figure_names.select[@id]
if b == "Grundkarte.png"
if @pic_ID1 == -1
$game_variables[10] = $game_variables[10] + 1
@pic_ID1 = @id
@pic_changer.change_card()
#change_card()
elsif @pic_ID2 == -2
$game_variables[10] = $game_variables[10] + 1
@pic_ID2 = @id
@pic_changer.change_card()
#change_card()
end
else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
Audio.se_play("Buzzer1", 80, 100)
end
$game_variables[10] = $game_variables[10] + 1
end

end
return @pic_ID1, @pic_ID2
end

#Hier findet die Bewegung des Mauszeigers statt.
def move_cursor
@cursor.x = @x_nav
@cursor.y = @y_nav
end

#hier wird der Ton abegespielt wenn sich der Spieler nicht mehr bewegen kann.
def move_error
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
end

end


Sorry dass der Code erst jetzt kommt :(

Linkey
02.07.2015, 16:15
Ich esse jetzt gleich erst einmal und bin noch was unterwegs, schaue mir das aber später noch an und editiere es hier rein. Erst einmal zur ersten Zeile vorab:

Beim Aufruf einer Methode, übergibst du nicht die Variable an sich, sondern den Wert, den sie besitzt. Beispiel:


def methode_a()
methode_b(5) # gibt aus: 5
methode_b(iZahl) #gibt aus: nil, da iZahl in methode_a gar nicht vorhanden ist
methode_b(rand(10)) #gibt eine zufällige Zahl zwischen 0 und 10 aus
varzahl = 1
methode_b(varzahl) #gibt 1 aus
end

def methode_b(iZahl)
p(iZahl)
end


Das ist bei Methoden mit Rückgabenwerte auch so. Es ist "egal", wie die Variablen in der aufrufenden Methode heißen.

Edit:
Was mir direkt aufgefallen ist,du hast anstelle einer Init-Methode deine ganzen Befehle in die navigae Methode gehauen. D.h, immer wenn die Methode aufgerufen wird, erstellst du neue Game_Memory, Memory_Picture_Changer Objekte. Das sieht falsch aus. Pack das mal in eine Init-Methode. Ich kann es aber wie gesagt später noch korrigieren, wenn ich die Zeit dafür habe.

Edit2:
So, gerade fertig gegessen. So sollte deine Navigate Klasse dann mit den Korrekturen aussehen (warum du plötzlich in allen Methoden Objekte der "Memory_Klasse" anlegst, habe ich übrigens nicht verstanden):


# Hier findet die Navigation statt.
class Memory_Game_Navigate

def initialize
@cursor = Sprite.new
#Kommentar: Die meisten Sprites liegen im Z-Wert zwischen 0 und 300.
#Mit 500 solltest du auf jeden Fall auf der obersten Ebene sein, wodurch
#dein Cursor über allem steht.
@cursor.z = 500
@cursor.bitmap = Cache.picture("Stern_1.PNG")
@x_nav = 0
@y_nav = 0
@id = 0
@pic_ID1 = -1
@pic_ID2 = -2
@win = 0

@pic_changer = Memory_Picture_Changer.new
end


def navigate
# f_wrapper enthält die Deckblätter
# f_names enthält die Bilder
# s_names enthält die Sounds
f_wrapper, f_names, s_names = $game_system.memory.get_arrays()

if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nav + 104
@id = @id + 4
move_cursor()
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
move_error()
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
move_cursor()
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nav - 104
@id = @id - 4
move_cursor()
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
move_error()
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
move_cursor()
end
end

if Input.trigger?(:C)
a = f_names[@id]
b = f_wrapper[@id]
#a = @figure_names.select[@id]
if b == "Card_000.png"
if @pic_ID1 == -1
$game_variables[10] = $game_variables[10] + 1
@pic_ID1 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
#change_card()
elsif @pic_ID2 == -2
$game_variables[10] = $game_variables[10] + 1
@pic_ID2 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
#change_card()
end
else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
Audio.se_play("Buzzer1", 80, 100)
end
$game_variables[10] = $game_variables[10] + 1
end

end
return @pic_ID1, @pic_ID2
end

#Hier findet die Bewegung des Mauszeigers statt.
def move_cursor
@cursor.x = @x_nav
@cursor.y = @y_nav
end

#hier wird der Ton abegespielt wenn sich der Spieler nicht mehr bewegen kann.
def move_error
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
end

end

Elster
04.07.2015, 14:58
Danke für die schönen Änderungen in meiner Klasse Linkey :3

@Edit 2:
Öhm... teilweise zum herumprobieren. Zudem muss ich ja zumindest in der Methode "change_card" auf die Methode "update_graphics" zugreifen, welche in Game_Memory liegt.
Mag sein das da wieder ein Denkfehler meinerseits vorhanden ist.


Mjoar, hm, aber was ich gerade wirklich nicht verstehe ist ein Fehler in folgender Zeile:

@f_wrapper.map! {|x| x == pID1 ? @c : x}.flatter

Da soll jetzt irgndwo was "nil" sein, also irgendwo herrscht gähnende Leere... ich sehe aber rein gar nichts, dass hier leer sein könnte.


undifined method `map!' for nil:NilClass

Was ich mir noch vorstellen könnte wäre, dass das Programm nicht so ganz mit "map" klar kommt.
Dann stellt sich aber bei mir die Frage, wie überschreibe ich denn dann die Einträge in dem Array?

Kelven
04.07.2015, 15:55
@f_wrapper selbst ist nil. In deiner Methode "navigate" sehe ich eigentlich auch nur eine lokale Variable f_wrapper, also ohne @. Wo kommt denn der Aufruf, der im Code-Block steht?

Linkey
04.07.2015, 16:40
Wie Kelven schon sagt, setzt du die Variable als lokale Variable (ohne @) hier:

f_wrapper, f_names, s_names = $game_system.memory.get_arrays()
f_wrapper sollte funktionieren - @f_wrapper ist nicht deklariert, also nil.

Bezüglich des mehrfachen anlegens von Game_Memory:
Die Game_Memory-Klasse sollte exakt ein Objekt für das Spiel verwenden (zumal du in Game_Memory dein Array mischst. Dadurch hat ja jede neuangelegte Instanz der Klasse ein anderes Array).
Du hast ja das erstellte Game_Memory Objekt bereits global im Zugriff:
$game_system.memory

D.h. wenn du nun die Update-Methode von Game_Memory verwenden willst, kannst du es wie folgt machen:

$game_system.memory.update_graphics

Cepanks
04.07.2015, 17:17
@f_wrapper.map! {|x| x == pID1 ? @c : x}.flatter
Noch was. Das "flatter" sollte vermutlich flatten (http://ruby-doc.org/core-1.9.3/Array.html#method-i-flatten) heißen? Außer du hast irgendwo eine Methode "flatter" für die Array-Klasse geschrieben, dann passt es.

Elster
07.07.2015, 15:38
@Cepanks
jab, meinte "flattern" ... kommt davon wenn man in den Weiten des Internets sucht und halbwegs richtige Lösungen für sein Problem findet ^^

@Linkey


$game_system.memory.update_graphics

Ich habe das mal an den entsprechenden Stellen eingefügt, jetzt mosert aber das Programm herum, dass die Methode nicht für Game_Memory definiert sei.
Liegt vermutlich daran, dass update_graphics in der Klasse "Scene_Memory" liegt.
Dann geht der Code wohl so nicht und ich müsste ein neues Objekt von Scene_Memory anlegen... oder?

Linkey
07.07.2015, 16:54
Hallo Elster,

super, habe kurz noch einmal auf dein Coding geschaut. Du brauchst die update_graphic-Aufrufe gar nicht.Deine Scene_Memory wird ja permanent geupdated. Und in der Update-Methode hast du folgendes:

def update
super
update_graphics
@navi.navigate
end

Du rufst update_graphics also permanent auf. Es ist also nicht nötig, diese Methode noch mehrmals aufzurufen, wenn diese eh schon permanent aufgerufen wird.
Nimm den Befehl aus deinen anderen Klassen daher ganz raus.

Edit:
Kurz noch einmal drüber geflogen, dein Rückgabewert in der navigate-Methode ist nicht nötig. Du gibst dort "id1 und id2" zurück, was keinen sinn macht. Die Methode wird ja von der Scene_Memory über die Update-Methode aufgerufen.
Was du aus performance Gründen noch eventuell machen könntest, dass du von der Navigate-Methode ein "true" zurückgibst, wenn Input::C aktiviert wurde und die Methode an sonsten ein false zurück gibt (die letzten Zeilen der Navigate Methode sollten dann ungefähr so aussehen:



return true
end
return false
end

#Hier findet die Bewegung des Mauszeigers statt.
def move_cursor


Dann könntest du in der Scene_Memory Update-Methode folgendes machen:


def update
super
update_graphics if(@navi.navigate)
end


Dadurch wird update_graphics nur ausgeführt, wenn Enter gedrückt wurde. Die Kartenbilder müssen ja nicht jede Sekunde geupdated werden, sondern nur bei Änderungen, welche ja eigentlich nur bei "Enter" geschehen können.

Elster
08.07.2015, 15:50
Gut, sieht schon mal besser aus, danke.
Nur... wenn ich etwas anklicke, habe ich wieder den zweiten Mauszeiger, oben links in der Ecke.

Auch wird das Bild an der Koordinate nicht geändert.

ebenso dachte ich, ich würde schon abfangen, dass man Karten nicht doppelt anklicken kann =/
Gut, sollte eigentlich auch mit:

if b == "Grundkarte.png"
funktionieren... nur werden eben die Karten im Array nicht geändert...
Eigentlich sollten das doch folgende Codezeilen hinbekommen oder?


if pID1 != -1
@c = f_names[pID1]
f_wrapper.map! {|x| x == pID1 ? @c : x}.flatten
end


Was mir auch noch Sorgen bereitet, das Memory findet Paare nicht. Nur wenn ich zwei mal auf die selbe Stelle klicke, meint es ich hätte was passendes gefunden, dabei sollte es doch gleiche Kartennamen erkennen.
Wenn... ich mir aber meinen Code anschaue.... oh mist.... ich arbeite mit den IDs bezüglich der Paarfindung... dann kann das natürlich nicht gehen. -_-'
Also haut meine Werte Abfrage...

if pID1 == pID2
... tatsächlich nur dann hin... wenn ich zweimal auf die selbe Stelle klicke... (warum ist mir das nicht eher aufgefallen? *facepalm*)
Hab ich auch mal einen Fehler gefunden..... und tatsächlich beseitigt bekommen O_O

Naja aber die anderen bereiten mir echt Kopfzerbrechen...

Momentan sieht der Code im Ganzen so aus und... läuft auch... nur eben mit "n" Mauszeigern und keiner Bildanpassung.


class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize

#Deckkarten
@figure_wrapper = [
"Grundkarte.png", "Grundkarte.png", #1
"Grundkarte.png", "Grundkarte.png", #2
"Grundkarte.png", "Grundkarte.png", #3
"Grundkarte.png", "Grundkarte.png", #4
"Grundkarte.png", "Grundkarte.png", #5
"Grundkarte.png", "Grundkarte.png", #6
"Grundkarte.png", "Grundkarte.png", #7
"Grundkarte.png", "Grundkarte.png", #8
]

#Bilderkarten
@figure_names = [
"Spinne1.png", "Spinne1.png",
"Spinne2.png", "Spinne2.png",
"Spinne3.png", "Spinne3.png",
"Spinne4.png", "Spinne4.png",
"Spinne5.png", "Spinne5.png",
"Spinne6.png", "Spinne6.png",
"Spinne7.png", "Spinne7.png",
"Spinne8.png", "Spinne8.png",
].shuffle

#Sounds für die Tonvariante
@sound_names = [
"Up1", "Up1", #1
"Thunder3", "Thunder3", #2
"Sword4", "Sword4", #3
"Switch2", "Switch2", #4
"Stare", "Stare", #5
"Shop", "Shop", #6
"Saint9", "Saint9", #7
"Miss", "Miss" #8
].shuffle

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
#0, 208,
#136, 208,
#272, 208,
#408, 208,
#
#0, 312,
#136, 312,
#272, 312,
#408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 136
@card_height = 104
# distance between cards
@margin = 0
# number of possible moves
@move = 32
# number of right pairs found. Win at 8
# change in def change_card for your game
#@win = 0
p @figure_names
#p @positions

end

def get_arrays
return @figure_wrapper, @figure_names, @sound_names
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
#@figure_names[index]
@figure_wrapper [index]
#@figure_names[@positions[index]]
end

# number of different figures/cards
def number_of_pictures
#p "number_of_pictures"
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
#p "shuffle_cards"
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end


class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base

def initialize_graphics
#for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
@navi = Memory_Game_Navigate.new
end

def update_graphics
#update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics if(@navi.navigate)
end

#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def start #(start)
super
initialize_graphics
update
end

end

#-------------------------------------------------------------------------------
# Hier findet das Verändern der Deckbilder statt.
# Ich sollte nach gleichen Namen schauen und wenn diese gleich sind, wird das
# Deckblatt entgültig entfernt.
#-------------------------------------------------------------------------------

class Memory_Picture_Changer

def initialize
@win = 0
end

#Ändert die angezeigten Bilder.
# TODO Tonvariante einpflegen
def change_card(pID1,pID2)
@navigater = Memory_Game_Navigate.new
f_wrapper, f_names, s_names = $game_system.memory.get_arrays()
p pID1, pID2
#zeigt die erste umgedeckte Karte an.
if pID1 != -1
@c = f_names[pID1]
f_wrapper.map! {|x| x == pID1 ? @c : x}.flatten
#$game_system.memory.update_graphics
end

#zeigt die zweite umgedeckte Karte an.
if pID2 != -2
@d = f_names[pID2]
f_wrapper.map! {|x| x == pID1 ? @d : x}.flatten #flatter
#$game_system.memory.update_graphics
end

if (pID1 != -1 && pID2 != -2)
#Wenn die Karten gleich sind!
p @c, @d
if @c == @d
RPG::SE.new("Chime2", 80, 100).play
pID1 = -1
pID2 = -2
@win = @win + 1
#Wenn die Karten ungleich sind!
else #(pID1 != pID2)
RPG::SE.new("Buzzer2", 80, 100).play
pic = "Grundkarte.png"
f_wrapper.map! {|x| x == pID1 ? pic : x}.flatten
f_wrapper.map! {|y| y == pID2 ? pic : y}.flatten
pID1 = -1
pID2 = -2
#$game_system.memory.update_graphics
end
end
return pID1,pID2
end
end



# Hier findet die Navigation statt.
class Memory_Game_Navigate

def initialize
@cursor = Sprite.new
#Kommentar: Die meisten Sprites liegen im Z-Wert zwischen 0 und 300.
#Mit 500 solltest du auf jeden Fall auf der obersten Ebene sein, wodurch
#dein Cursor über allem steht.
@cursor.z = 500
@cursor.bitmap = Cache.picture("Zeiger.png")
@x_nav = 0
@y_nav = 0
@id = 0
@pic_ID1 = -1
@pic_ID2 = -2
#@win = 0

@pic_changer = Memory_Picture_Changer.new
end


def navigate
# f_wrapper enthält die Deckblätter
# f_names enthält die Bilder
# s_names enthält die Sounds
f_wrapper, f_names, s_names = $game_system.memory.get_arrays()

if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nav + 104
@id = @id + 4
move_cursor()
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
move_error()
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
move_cursor()
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nav - 104
@id = @id - 4
move_cursor()
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
move_error()
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
move_cursor()
end
end

if Input.trigger?(:C)
a = f_names[@id]
b = f_wrapper[@id]
if b == "Grundkarte.png"
if @pic_ID1 == -1
$game_variables[10] = $game_variables[10] + 1
@pic_ID1 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
elsif @pic_ID2 == -2
$game_variables[10] = $game_variables[10] + 1
@pic_ID2 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
end
else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
Audio.se_play("Buzzer1", 80, 100)
end
$game_variables[10] = $game_variables[10] + 1
end
return true
end
#return @pic_ID1, @pic_ID2
return false
end

#Hier findet die Bewegung des Mauszeigers statt.
def move_cursor
@cursor.x = @x_nav
@cursor.y = @y_nav
end

#hier wird der Ton abegespielt wenn sich der Spieler nicht mehr bewegen kann.
def move_error
if $game_switches[2] == true
Audio.se_play("Earth6", 80, 100)
end
end
end

Linkey
08.07.2015, 19:49
Hallo Elster,

das Problem mit den mehrfachen Zeigern, du erstellst - unnötig - ein Objekt der Navigate Klasse direkt in der change Methode. Diese musst du rausnehmen:

def change_card(pID1,pID2)
@navigater = Memory_Game_Navigate.new

Edit:
So, habe mir den Rest mal schnell überflogen. Folgendes Problem hast du noch in deiner change_pic Methode:
Die folgende Zeile:

f_wrapper.map! {|x|x == pID1 ? @c : x}.flatten
Geht über das Array und prüft dann jedes Element auf "pID1". Die Elemente sind aber alle "Grundkarte.png" und daher ist die Abfrage nie richtig.

Richtig lautet es wie folgt:

f_wrapper.map!.with_index {|x,i|i == pID1 ? @c : x}.flatten
Durch den Zusatz "with_index" wird der Index der Position des Arrays mit gegeben. Diese wird durch die Variable "i" dann im Befehl festgehalten und du prüft dann pID1 auf i. So klappt es dann, dass pID mit der Array-Position verglichen wird.

Das musst du in den anderen ".map!"-Verwendungen in der Change_Pic-Methode so anpassen.

Elster
09.07.2015, 10:31
Omg es funktioniert!!!!!
ES FUNKTIONIERT!!!!!!

DANKE! DANKE! DANKE! DANKE! DANKE! ^_^

Ich weiß das ich damit noch nicht ganz fertig bin und ein paar Sachen fehlen... aber ES FUNKTIONERT!
Jetzt muss ich nur ein Ende einbauen wenn ich alle Karten umgedreht habe oder zu viele Züge gemacht wurden. (Gut und ich wollte eine zweite Variante Einfügen... aber das sollte nachdem das steht nicht mehr das Problem sein)

DANKE!!!!!

Linkey, Cepanks, -KD- und Kelven durchknuddel

Linkey
09.07.2015, 12:31
Immer wieder gerne. Wir sind ja hier, weil wir gerne bei technischen Fragestellungen helfen.
Wenn du dabei noch etwas gelernt hast ist es wunderbar (:

Ich hoffe, wir bekommen was zu sehen, wenn es irgendwann mal komplett fertig ist und es ein "Spiel" dazu gibt :)

Elster
13.07.2015, 12:13
Okay, ich bin äußerst gut darin mein Skript zu beenden, sehr gut so gar..... ich würde fast sagen zu gut!
Ich kann hervorragend das gesammte Spiel beenden... wunderbar oder?

Mal so am Rande... gibt es eine Möglichkeit ein Skript einfach zu stoppen ohne das gesammte Spiel abzuschalten oder den Bildschirm dabei einzufrieren?
Für so ein "Minispiel" wirklich ärgerlich... wenn man es nicht beenden/gewinnen kann O_o

Ich finde im Netz auch nur was wie ich es halt davon abhalte zu starten... was ich ja nicht will.

Kelven
13.07.2015, 15:48
Eigentlich müsstest du nur wieder zur Map-Szene zurückwechseln können. Und zwar mit der Methode return_scene.

Linkey
13.07.2015, 19:06
Diese Methode funktioniert aber nur, wenn du diese in Scene_Memory verwendest, da die Methode in Scene_Base deklariert ist (und Scene_Memory von Scene_Base erbt).

Elster
25.07.2015, 12:42
Das hat so funktioniert ^^


Dennoch habe ich gerade ein anderes, mich arg verwirrendes Problem.
Die Kartenvariante funktioniert noch immer ohne Probleme (ok sie hat einen Schönheitsfehler und vielleicht hat einer von euch eine Idee wie man den beseitigen kann)

Dennoch, in meiner Klangvariante gibt es etwas, das mich wirklich stutzig macht.
Das passiert, jetzt zumindest nur noch, beim ersten Zug. Hier kann ich einmalig eine einzige Karte zwei mal anklicken um ein Paar zu finden... und dann ist die auch umgeschrieben so das ich unmöglich mit der anderen, gleichen Karte noch ein Paar bilden kann.
Weiterhin kann ich (das gesammte Spiel über) zwei Mal auf die selben Stelle im Memory klicken und ich kann zwei mal ein Paar finden, erst danach wird es endgültig als gefunden deklariert und die Karten können nicht mehr angeklickt werden.
Genauer erklärt: ich drücke auf A1 u. A2 (da liegen nun zusammen ein paar und ich höre das Geräusch für gefunden und der Zähler um zu gewinnen wird einen hoch gezählt) jetzt kann ich noch einmal A1 u. A2 anklicken... danach kann ich sie aber nicht mehr anklicken. Beim besten Willen, ich kann mir das nicht erklären :(
Ich kann also mit einem Paar Doppel abräumen. Hilfe ^^"

So und nun zum kleinen "Schönheitsfehler". In der Bildvariante wird die zweite Karte nicht umgedreht, wenn ein Kartenpaar nicht zusammen passt. Ergo sieht der Spieler nicht, was sich unter Karte 2 befindet. Ich habe versucht, da ein Programm ja extrem schnell arbeitet, den Prozess des Zurückdrehens mit einem "sleep" herauszuzögern... aber da wartet das Programm nur doof ab und zeigt auch kein Bild an, egal wo ich es einbaue.
Jemand eine Idee wie ich dem Spieler noch kurzzeitig Karte 2 zeigen kann?
Ansonsten hier einmal der komplette Code, mit der schönen verbugten Tonvariante... wenn jemand den Fehler findet, warum ich ein paar zweimal finden kann, wäre ich sehr danbar. Für den anderen Fehler natürlich auch.



class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize
#Deckkarten
@figure_wrapper = [
"Grundkarte.png", "Grundkarte.png", #1
"Grundkarte.png", "Grundkarte.png", #2
"Grundkarte.png", "Grundkarte.png", #3
"Grundkarte.png", "Grundkarte.png", #4
"Grundkarte.png", "Grundkarte.png", #5
"Grundkarte.png", "Grundkarte.png", #6
"Grundkarte.png", "Grundkarte.png", #7
"Grundkarte.png", "Grundkarte.png", #8
]

#Deckkarten 2 ... für den blinden Spieler
@figure_wrapper_2 = [
"Blanco.png", "Blanco.png", #1
"Blanco.png", "Blanco.png", #2
"Blanco.png", "Blanco.png", #3
"Blanco.png", "Blanco.png", #4
"Blanco.png", "Blanco.png", #5
"Blanco.png", "Blanco.png", #6
"Blanco.png", "Blanco.png", #7
"Blanco.png", "Blanco.png", #8
]

#Bilderkarten
@figure_names = [
"Spinne1.png", "Spinne1.png",
"Spinne2.png", "Spinne2.png",
"Spinne3.png", "Spinne3.png",
"Spinne4.png", "Spinne4.png",
"Spinne5.png", "Spinne5.png",
"Spinne6.png", "Spinne6.png",
"Spinne7.png", "Spinne7.png",
"Spinne8.png", "Spinne8.png",
].shuffle

#Sounds für die Tonvariante
@sound_names = [
"Up1", "Up1", #1
"Thunder3", "Thunder3", #2
"Sword4", "Sword4", #3
"Switch2", "Switch2", #4
"Stare", "Stare", #5
"Shop", "Shop", #6
"Saint9", "Saint9", #7
"Miss", "Miss" #8
].shuffle

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
#0, 208,
#136, 208,
#272, 208,
#408, 208,
#
#0, 312,
#136, 312,
#272, 312,
#408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 136
@card_height = 104
# distance between cards
@margin = 0
# number of possible moves
#@move = 32
# number of right pairs found. Win at 8
# change in def change_card for your game
p @figure_names
p @sound_names
end

def get_arrays
return @figure_wrapper, @figure_wrapper_2, @figure_names, @sound_names
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
#@figure_wrapper [index]
if $game_switches[2] != true
@figure_wrapper [index]
elsif $game_switches[2] == true
@figure_wrapper_2 [index]
end
end

# number of different figures/cards
def number_of_pictures
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end


class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base

def initialize_graphics
#for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
@navi = Memory_Game_Navigate.new
end

def update_graphics

#update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics if(@navi.navigate)
end

#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def start #(start)
super
initialize_graphics
update
end

end

#-------------------------------------------------------------------------------
# Hier findet das Verändern der Deckbilder statt.
# Ich sollte nach gleichen Namen schauen und wenn diese gleich sind, wird das
# Deckblatt entgültig entfernt.
#-------------------------------------------------------------------------------

class Memory_Picture_Changer

def initialize
@win = 0
@zug = 0
@c = "a"
@d = "b"
@c2 = "c"
@d2 = "d"
# Dient dazu, dass der erste Kartenklang nur einmal abgespielt wird,
# ohne @w wird er es sonst zweimal und überlagert halb den Klang der
# zweiten Karte.
@w = 2
end

#Ändert die angezeigten Bilder.
# TODO Tonvariante einpflegen
def change_card(pID1,pID2)
f_wrapper, f_wrapper_2, f_names, s_names = $game_system.memory.get_arrays()
#zeigt die erste umgedeckte Karte an.
if pID1 != -1
if $game_switches[2] != true
@c = f_names[pID1]
f_wrapper.map!.with_index {|x,i|i == pID1 ? @c : x}.flatten
end
if $game_switches[2] == true && @w != 1
@c3 = "Blanco_2.png"
@c2 = s_names[pID1]
RPG::SE.new(@c2, 80, 100).play
@w = 1
f_wrapper_2.map!.with_index {|x,i|i == pID1 ? @c3 : x}.flatten
end
end

#zeigt die zweite umgedeckte Karte an.
if pID2 != -2
if $game_switches[2] != true
@d = f_names[pID2]
@zug = @zug + 2
f_wrapper.map!.with_index {|y,i| i == pID2 ? @d : y}.flatten
end

if $game_switches[2] == true
@d3 = "Blanco_2.png"
@d2 = s_names[pID2]
RPG::SE.new(@d2, 80, 100).play
@zug = @zug + 2
f_wrapper.map!.with_index {|y,i| i == pID2 ? @d3 : y}.flatten
end

end

if (pID1 != -1 && pID2 != -2 )
#Wenn die Karten gleich sind!
if @c == @d #|| @c2 == @d2
pID1 = -1
pID2 = -2
@win = @win + 1
win_loose()
#Wenn die Karten ungleich sind!
elsif @c2 == @d2
RPG::SE.new("Chime2", 80, 100).play
pID1 = -1
pID2 = -2
@win = @win + 1
@w = 2
win_loose()
else
#(pID1 != pID2)
if $game_switches[2] != true
pic = "Grundkarte.png"
#sleep(1)
f_wrapper.map!.with_index {|x,i| i == pID1 ? pic : x}.flatten
f_wrapper.map!.with_index {|y,i| i == pID2 ? pic : y}.flatten
pID1 = -1
pID2 = -2
win_loose()
end
if $game_switches[2] == true
RPG::SE.new("Buzzer2", 80, 100).play
pic = "Blanco.png"
f_wrapper_2.map!.with_index {|x,i| i == pID1 ? pic : x}.flatten
f_wrapper_2.map!.with_index {|y,i| i == pID2 ? pic : y}.flatten
pID1 = -1
pID2 = -2
@w = 2
win_loose()
end
end
end
return pID1,pID2
end

#Siegbedingungen des Spiels
def win_loose
p @zug
p "Züge"
p @win
#Spiel gewonnen
if @win == 8 && @zug != 32
if $game_switches[2] == true
# TODO klar machen das der Spieler gewonnen hat.
end
$game_switches[17] = true
SceneManager.return
end

#Spiel gewonnen
if @win == 8 && @zug == 32
if $game_switches[2] == true
# TODO klar machen das der Spieler gewonnen hat.
end
$game_switches[17] = true
SceneManager.return
end

#Spiel verloren
if @win != 8 && @zug == 32
if $game_switches[2] == true
# TODO klar machen das der Spieler verloren hat.
end
#RPG::SE.new("Fire9", 80, 100).play
$game_switches[16] = true
SceneManager.return
end
end

end

# Hier findet die Navigation statt.
class Memory_Game_Navigate

def initialize
@cursor = Sprite.new
#Kommentar: Die meisten Sprites liegen im Z-Wert zwischen 0 und 300.
#Mit 500 solltest du auf jeden Fall auf der obersten Ebene sein, wodurch
#dein Cursor über allem steht.
@cursor.z = 500
if $game_switches[2] == false
@cursor.bitmap = Cache.picture("Zeiger.png")
end
@x_nav = 0
@y_nav = 0
@id = 0
@pic_ID1 = -1
@pic_ID2 = -2
@pic_changer = Memory_Picture_Changer.new
end


def navigate
# f_wrapper enthält die Deckblätter
# f_names enthält die Bilder
# s_names enthält die Sounds
f_wrapper, f_wrapper_2, f_names, s_names = $game_system.memory.get_arrays()

if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nav + 104
@id = @id + 4
move_cursor()
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
move_error()
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
move_cursor()
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nav - 104
@id = @id - 4
move_cursor()
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
move_error()
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
move_cursor()
end
end

if Input.trigger?(:C)
a = f_names[@id]
b = f_wrapper[@id]
c = f_wrapper_2[@id]
if b == "Grundkarte.png" #|| b == "Blanco.png"
if @pic_ID1 == -1
$game_variables[10] = $game_variables[10] + 1
@pic_ID1 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
elsif @pic_ID2 == -2
$game_variables[10] = $game_variables[10] + 1
@pic_ID2 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
end
elsif c == "Blanco.png"
if @pic_ID1 == -1
$game_variables[10] = $game_variables[10] + 1
@pic_ID1 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
elsif @pic_ID2 == -2
$game_variables[10] = $game_variables[10] + 1
@pic_ID2 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
end

else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
RPG::SE.new("Buzzer1", 80, 100).play
end
$game_variables[10] = $game_variables[10] + 1
end
return true
end
return false
end

#Hier findet die Bewegung des Mauszeigers statt.
def move_cursor
if $game_switches[2] == true
RPG::SE.new("Switch1", 80, 100).play
end
@cursor.x = @x_nav
@cursor.y = @y_nav
end

#hier wird der Ton abegespielt wenn sich der Spieler nicht mehr bewegen kann.
def move_error
if $game_switches[2] == true
RPG::SE.new("Earth6", 80, 100).play
end
end
end

Linkey
26.07.2015, 21:05
Hey Elster :)

Wenn ich das richtig sehe, verwendest du "Blanco" nur bei der Sound-Methode. Daher gibt es das Problem, dass egal in welchem Modi du bist, die andere Abfrage dann funktioniert - da hier die Felder alle immer entweder Blanco oder Grundkarte sind. Du musst daher in deine Input:C Abfrage auch noch den Switch[2] abfragen:


[...]
if b == "Grundkarte.png" && $game_switches[2] == false
[....]
elsif c == "Blanco.png" && $game_switches[2]
[....]

Dazu kommt noch, dass du einen Fehler eingebaut hast, in der Changer Methode. Dort verwendest du bei einer der beiden pIDs den f_wrapper anstelle des f_wrapper_2 für die Sound-Methode. Wenn du die beiden Dinger korrigierst, sollte es gleich funktionieren.

Folgendes macht übrigens wenig Sinn (es sei denn das ist ein Platzhalter und es wird dort noch eine Sonderabfrage (unentschieden?) stattfinden in Zukunft):


if @win == 8 && @zug != 32
if $game_switches[2] == true
# TODO klar machen das der Spieler gewonnen hat.
end
$game_switches[17] = true
SceneManager.return
end

#Spiel gewonnen
if @win == 8 && @zug == 32
if $game_switches[2] == true
# TODO klar machen das der Spieler gewonnen hat.
end
$game_switches[17] = true
SceneManager.return
end


Sobald @win == 8 ist, trifft eine der beiden Abfragen zu. Da diese den gleichen Inhalt haben, ist die Doppelung durch die Abfragen auf @zug = 32 oder != 32 überflüssig.

Außerdem ist dein "Else" bei der Navigate Methode sinnlos. Dort zählst du Variable[10] hoch - diese wird aber nirgends verwendet. Warum auch? Ist es tatsächlich ein Zug, wenn man eine bereits aufgedeckte Karte anklickt? Hier scheint ein Logikfehler vorzuliegen.

@Schönheitsfehler:
Ein einfaches sleep reicht dort nicht. Du bist darauf angewiesen, dass deine Methode etwas zurückgibt, damit das Update durchgeführt wird.

def update
super
update_graphics if(@navi.navigate)
end
D.h. wenn du innerhalb des navigate Aufrufes ein sleep setzt, wird auch die Rückgabe an deine update Methode verzögert. Du musst es also so umsetzen, dass die Karte umgedreht wird - die Methode einen Wert zurückliefert - und erneut in die Methode springt und dort dann das Umdrehen beider Karten vornimmt.
Hierfür bietet es sich an, einen Timer oder eine Tastenabfrage einzubauen.

Habe dir das einmal in deinen Code eingefügt:


class Game_Memory
# hier kommen alle Attribute rein die dein Spiel so hat

# filenames of the pictures of your cards
attr_accessor :figure_names

def initialize
#Deckkarten
@figure_wrapper = [
"Grundkarte.png", "Grundkarte.png", #1
"Grundkarte.png", "Grundkarte.png", #2
"Grundkarte.png", "Grundkarte.png", #3
"Grundkarte.png", "Grundkarte.png", #4
"Grundkarte.png", "Grundkarte.png", #5
"Grundkarte.png", "Grundkarte.png", #6
"Grundkarte.png", "Grundkarte.png", #7
"Grundkarte.png", "Grundkarte.png", #8
]

#Deckkarten 2 ... für den blinden Spieler
@figure_wrapper_2 = [
"Blanco.png", "Blanco.png", #1
"Blanco.png", "Blanco.png", #2
"Blanco.png", "Blanco.png", #3
"Blanco.png", "Blanco.png", #4
"Blanco.png", "Blanco.png", #5
"Blanco.png", "Blanco.png", #6
"Blanco.png", "Blanco.png", #7
"Blanco.png", "Blanco.png", #8
]

#Bilderkarten
@figure_names = [
"Spinne1.png", "Spinne1.png",
"Spinne2.png", "Spinne2.png",
"Spinne3.png", "Spinne3.png",
"Spinne4.png", "Spinne4.png",
"Spinne5.png", "Spinne5.png",
"Spinne6.png", "Spinne6.png",
"Spinne7.png", "Spinne7.png",
"Spinne8.png", "Spinne8.png",
].shuffle

#Sounds für die Tonvariante
@sound_names = [
"Up1", "Up1", #1
"Thunder3", "Thunder3", #2
"Sword4", "Sword4", #3
"Switch2", "Switch2", #4
"Stare", "Stare", #5
"Shop", "Shop", #6
"Saint9", "Saint9", #7
"Miss", "Miss" #8
].shuffle

@positions = [
0, 0,
136, 0,
272, 0,
408, 0,
#
0, 104,
136, 104,
272, 104,
408, 104,
#
#0, 208,
#136, 208,
#272, 208,
#408, 208,
#
#0, 312,
#136, 312,
#272, 312,
#408, 312
]
# number of cards horizontal
@max_number_of_cols = 4
# size of cards
@card_width = 136
@card_height = 104
# distance between cards
@margin = 0
# number of possible moves
#@move = 32
# number of right pairs found. Win at 8
# change in def change_card for your game
p @figure_names
p @sound_names
end

def get_arrays
return @figure_wrapper, @figure_wrapper_2, @figure_names, @sound_names
end

# returns x, y coordinates as well as the image name of
# the card with the given index
def get_card index
[card_x(index), card_y(index), card_image(index)]
end

# return all cards
def get_cards
# create a new array with elements
# for all indizes from 0 upto @positions.size
(0...@positions.size).map do |index|
# each element contains the result value of
# get_card
get_card index
end
end

# x coordinate for a given card index
def card_x index
col_num = index % @max_number_of_cols
col_num * (@card_width + @margin)
end

# y coordinate for a given card index
def card_y index
row_num = index / @max_number_of_cols
row_num * (@card_height+@margin)
end

# filename of card image
def card_image index
#@figure_wrapper [index]
if $game_switches[2] != true
@figure_wrapper [index]
elsif $game_switches[2] == true
@figure_wrapper_2 [index]
end
end

# number of different figures/cards
def number_of_pictures
@figure_names.size
end

# add 2 cards for each figure into the field
# shuffle the positions of all cards
def shuffle_cards
@positions.clear
# this loop is invoked as often as the number
# of different cards
number_of_pictures.times do |picture_id|
# for each invocation, two cards are added
# into the array
@positions << picture_id << picture_id
end
# shuffle the array at the end
@positions.shuffle!
end

end


class Game_System
# füge Memory als Attribut hinzu
attr_accessor :memory
end


# Erbebt von Scene_Base
class Scene_Memory < Scene_Base

def initialize_graphics
#for each card in the game
@card_sprites = $game_system.memory.get_cards.map do |x, y, image|
# create a new sprite
sprite = Sprite.new
# set its graphic and coordinates
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x, y
# and "return" the sprite into the array
sprite
end
@navi = Memory_Game_Navigate.new
end

def update_graphics

#update attributes of all sprites
@card_sprites.each_with_index do |sprite, index|
x, y, image = $game_system.memory.get_card(index)
sprite.bitmap = Cache.picture(image)
sprite.x, sprite.y = x,y
end
end

def dispose_graphics
@card_sprites.each do |sprite|
sprite.dispose
end
end

#-------------------------------------------------------------------------------
# überschreibt terminate Scene_Base
#-------------------------------------------------------------------------------
def terminate
super
dispose_graphics
end

#-------------------------------------------------------------------------------
# überschreibt update Scene_Base
#-------------------------------------------------------------------------------
def update
super
update_graphics if(@navi.navigate)
end

#-------------------------------------------------------------------------------
# Überschreibt start von Scene_Base
#-------------------------------------------------------------------------------
def start #(start)
super
initialize_graphics
update
end

end

#-------------------------------------------------------------------------------
# Hier findet das Verändern der Deckbilder statt.
# Ich sollte nach gleichen Namen schauen und wenn diese gleich sind, wird das
# Deckblatt entgültig entfernt.
#-------------------------------------------------------------------------------

class Memory_Picture_Changer

def initialize
@win = 0
@zug = 0
@c = "a"
@d = "b"
@c2 = "c"
@d2 = "d"
# Dient dazu, dass der erste Kartenklang nur einmal abgespielt wird,
# ohne @w wird er es sonst zweimal und überlagert halb den Klang der
# zweiten Karte.
@w = 2
end

#Ändert die angezeigten Bilder.
# TODO Tonvariante einpflegen
def change_card(pID1,pID2)
f_wrapper, f_wrapper_2, f_names, s_names = $game_system.memory.get_arrays()
#zeigt die erste umgedeckte Karte an.
if pID1 != -1
if $game_switches[2] != true
@c = f_names[pID1]
f_wrapper.map!.with_index {|x,i|i == pID1 ? @c : x}.flatten
end
if $game_switches[2] == true && @w != 1
@c3 = "Blanco_2.png"
@c2 = s_names[pID1]
RPG::SE.new(@c2, 80, 100).play
@w = 1
f_wrapper_2.map!.with_index {|x,i|i == pID1 ? @c3 : x}.flatten
end
end

#zeigt die zweite umgedeckte Karte an.
if pID2 != -2
if $game_switches[2] != true
@d = f_names[pID2]
@zug = @zug + 2
f_wrapper.map!.with_index {|y,i| i == pID2 ? @d : y}.flatten
end

if $game_switches[2] == true
@d3 = "Blanco_2.png"
@d2 = s_names[pID2]
RPG::SE.new(@d2, 80, 100).play
@zug = @zug + 2
f_wrapper_2.map!.with_index {|y,i| i == pID2 ? @d3 : y}.flatten
end

end
return pID1,pID2
end

def end_change(pID1,pID2)
f_wrapper, f_wrapper_2, f_names, s_names = $game_system.memory.get_arrays()
if (pID1 != -1 && pID2 != -2 )
#Wenn die Karten gleich sind!
if @c == @d #|| @c2 == @d2
pID1 = -1
pID2 = -2
@win = @win + 1
win_loose()
#Wenn die Karten ungleich sind!
elsif @c2 == @d2
RPG::SE.new("Chime2", 80, 100).play
pID1 = -1
pID2 = -2
@win = @win + 1
@w = 2
win_loose()
else
#(pID1 != pID2)
if $game_switches[2] != true
pic = "Grundkarte.png"
#sleep(1)
f_wrapper.map!.with_index {|x,i| i == pID1 ? pic : x}.flatten
f_wrapper.map!.with_index {|y,i| i == pID2 ? pic : y}.flatten
pID1 = -1
pID2 = -2
win_loose()
end
if $game_switches[2] == true
RPG::SE.new("Buzzer2", 80, 100).play
pic = "Blanco.png"
f_wrapper_2.map!.with_index {|x,i| i == pID1 ? pic : x}.flatten
f_wrapper_2.map!.with_index {|y,i| i == pID2 ? pic : y}.flatten
pID1 = -1
pID2 = -2
@w = 2
win_loose()
end
end
end
return pID1,pID2
end


#Siegbedingungen des Spiels
def win_loose
p @zug
p "Züge"
p @win
#Spiel gewonnen
if @win == 8 && @zug != 32
if $game_switches[2] == true
# TODO klar machen das der Spieler gewonnen hat.
end
$game_switches[17] = true
SceneManager.return
end

#Spiel gewonnen
if @win == 8 && @zug == 32
if $game_switches[2] == true
# TODO klar machen das der Spieler gewonnen hat.
end
$game_switches[17] = true
SceneManager.return
end

#Spiel verloren
if @win != 8 && @zug == 32
if $game_switches[2] == true
# TODO klar machen das der Spieler verloren hat.
end
#RPG::SE.new("Fire9", 80, 100).play
$game_switches[16] = true
SceneManager.return
end
end

end

# Hier findet die Navigation statt.
class Memory_Game_Navigate

def initialize
@cursor = Sprite.new
#Kommentar: Die meisten Sprites liegen im Z-Wert zwischen 0 und 300.
#Mit 500 solltest du auf jeden Fall auf der obersten Ebene sein, wodurch
#dein Cursor über allem steht.
@cursor.z = 500
if $game_switches[2] == false
@cursor.bitmap = Cache.picture("Zeiger.png")
end
@x_nav = 0
@y_nav = 0
@id = 0
@pic_ID1 = -1
@pic_ID2 = -2
@pic_changer = Memory_Picture_Changer.new
@wait = 0
end


def navigate
# f_wrapper enthält die Deckblätter
# f_names enthält die Bilder
# s_names enthält die Sounds
if(@wait > 0)
@wait -= 1
if(@wait == 0)
@pic_ID1,@pic_ID2 = @pic_changer.end_change(@pic_ID1,@pic_ID2)
return true
end
return false
end

f_wrapper, f_wrapper_2, f_names, s_names = $game_system.memory.get_arrays()

if Input.trigger?(:DOWN)
if @y_nav == 312
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht vergrößert.
elsif
@y_nav = @y_nav + 104
@id = @id + 4
move_cursor()
end
end

if Input.trigger?(:LEFT)
if @x_nav == 0
move_error()
#Wert wird nich verkleinert.
elsif
@x_nav = @x_nav - 136
@id = @id - 1
move_cursor()
end
end

if Input.trigger?(:UP)
if @y_nav == 0
#Hier wird der Ton für den 2. Modus abgespielt.
move_error()
#Wert wird nicht verkleinert.
elsif
@y_nav = @y_nav - 104
@id = @id - 4
move_cursor()
end
end

if Input.trigger?(:RIGHT)
if @x_nav == 408
move_error()
#Wert wird nich vergrößert.
elsif
@x_nav = @x_nav + 136
@id = @id + 1
move_cursor()
end
end

if Input.trigger?(:C)
a = f_names[@id]
b = f_wrapper[@id]
c = f_wrapper_2[@id]
if b == "Grundkarte.png" && $game_switches[2] == false#|| b == "Blanco.png"
if @pic_ID1 == -1
$game_variables[10] = $game_variables[10] + 1
@pic_ID1 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
elsif @pic_ID2 == -2
$game_variables[10] = $game_variables[10] + 1
@pic_ID2 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
@wait = 30
end
elsif c == "Blanco.png" && $game_switches[2]
if @pic_ID1 == -1
$game_variables[10] = $game_variables[10] + 1
@pic_ID1 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
elsif @pic_ID2 == -2
$game_variables[10] = $game_variables[10] + 1
@pic_ID2 = @id
@pic_ID1,@pic_ID2 = @pic_changer.change_card(@pic_ID1,@pic_ID2)
@wait = 30
end

else
#Falls der Spieler blind ist, wird hier ein Signal abgespielt
#sonst wird in beiden Fällen die Variable für die Züge
#hochgezählt.
if $game_switches[2] == true
RPG::SE.new("Buzzer1", 80, 100).play
end
$game_variables[10] = $game_variables[10] + 1
end
return true
end
return false
end

#Hier findet die Bewegung des Mauszeigers statt.
def move_cursor
if $game_switches[2] == true
RPG::SE.new("Switch1", 80, 100).play
end
@cursor.x = @x_nav
@cursor.y = @y_nav
end

#hier wird der Ton abegespielt wenn sich der Spieler nicht mehr bewegen kann.
def move_error
if $game_switches[2] == true
RPG::SE.new("Earth6", 80, 100).play
end
end
end


Edit:
Als Eklärung:
In deiner Pic-Changer Klasse ist die "pic_change methode" nun geteilt wurden. In der Change Methode werden jetzt nur noch die Pictures gesetzt - die Abfrage, ob die Bilder gleich sind oder nicht, wurde in die "end_change" Methode gepackt. Dadurch haben wir die Möglichkeit, die Events "Karte umdrehen" und "Karte wieder verdecken falls kein Paar" zu trennen.

Deine Update-Methode ruft nun "navigate auf". Diese Methode prüft nun als aller erstes, ob @wait > 0 ist. Wenn dies der Fall ist, wird @wait um 1 verringert und anschließend die Methode direkt wieder (mit dem Wert false - da kein Update der Grafiken erforderlich ist) zurückgegeben. Sobald @wait aber auf 0 steht, wird die "end_change" Methode aufgerufen und anschließend durch ein return true die Grafik wieder geupdated. Beim nächsten Sprung in die Methode ist @wait nicht mehr größer 0 und dadurch wird die Methode jetzt wieder wie gewohnt fortgesetzt (Tastenabfragen).

Der Waitbefehl wird gesetzt, wenn die 2. Karte umgedreht wird. Diese habe ich jetzt auf 30 gestellt. Du kannst da je nach Belieben auch eine höhrere oder kleinere Zahl einstellen.
Du kannst anstelle eines Timers aber auch eine Variable setzen und dann anstelle der Abfrage "@wait > 0" ein "variable == true" reinsetzen und innerhalb dieser Methode per Tastenabfrage (z.B. C für Enter) die Sequenz fortführen. Somit könnte der Spieler solange auf die Karte schauen, bis er weiterdrückt.

Hoffe es war einigermaßen verständlich - wenn du noch Fragen hast kannst du dich ansonsten gerne melden.

Edit 2:
Post überarbeitet. Hatte da etwas falsch verstanden. Sollte jetzt stimmen.

Elster
27.07.2015, 12:30
Vielen lieben Dank ^^
Es funktioniert wunderbar ^.^

Variable[10] brauche ich außerhalb des Memorys;)
Damit kann man dann Sachen bekommen, je nachdem wie viele Züge man gebraucht hat, fällt die Belohnung besser, oder eben schlechter aus.
Lässt sich mit einer einfachen Variable außerhalb des Memorys weit einfacher lösen.

Oder man könnte damit jetzt auch eine Rangliste noch erstellen. "Dein bestes Spiel" oder was einem noch so einfällt.

Linkey
30.07.2015, 21:55
Freut mich zu hören :)
Die Züge werden aber ja auch erhöht, wenn man auf bereits geöffnete Bilder klickt. Das macht ja nicht unbedingt Sinn. Da könntest du lieber die Variable[10] zum Ende füllen, wenn die Sieg- oder Niederlage-Bedingung erfüllt ist.

Viel Erfolg beim weiteren Skripten und vielleicht bis zur nächsten Fragestellung :)