Skip to main content

Overview

Memorice is a memory matching game where players flip clams to reveal items, then find matching pairs. The game features 10 distinct items (20 clams total) arranged in a 4x5 grid. Points decrease with incorrect matches, adding strategic pressure. Scene Path: res://minigames/memorice/scripts/memorice.gd

Cognitive Skills Developed

  • Short-Term Memory: Remembering locations of previously revealed items
  • Visual Recognition: Quickly identifying items when clams open
  • Spatial Memory: Tracking grid positions of items
  • Strategic Planning: Deciding which clams to open first
  • Pattern Recognition: Identifying which items have been seen

How to Play

Controls

  • Tap Clam: Open to reveal item inside
  • Back Button: Pause game

Objective

Match all 10 pairs before running out of points.

Gameplay Flow

  1. Preview: All clams open for 5 seconds showing all items
  2. Memorization: Study item positions
  3. Close: Clams close and game begins
  4. Match: Click two clams to find matching items
  5. Repeat: Continue until all pairs matched or points reach 0

Scoring System

Starting Points

var puntos = 100
Players start with 100 points.

Point Changes

if primera_seleccion.objeto_id == segunda_seleccion.objeto_id:
    # Correct match
    puntos += 100
    _mostrar_texto_flotante(primera_seleccion.global_position, "+100", Color(0, 1, 0))
else:
    # Wrong match
    puntos = max(puntos - 50, 0)
    _mostrar_texto_flotante(primera_seleccion.global_position, "-50", Color(1, 0, 0))
  • Correct Match: +100 points
  • Wrong Match: -50 points (minimum 0)
  • Game Over: Points reach 0
  • Victory: All pairs matched

Coin Conversion

var coins_earned = int(puntos * 0.5)
score_manager.add_coins(coins_earned)
Coins = 50% of final score

Item Types

The game features 10 unique items (2 of each):
var escenas = [
    preload("res://minigames/memorice/scenes/almeja_camaron.tscn"),
    preload("res://minigames/memorice/scenes/almeja_zapatilla.tscn"),
    preload("res://minigames/memorice/scenes/almeja_lata.tscn"),
    preload("res://minigames/memorice/scenes/almeja_gusano.tscn"),
    preload("res://minigames/memorice/scenes/almeja_alga.tscn"),
    preload("res://minigames/memorice/scenes/almeja_plastico.tscn"),
    preload("res://minigames/memorice/scenes/almeja_botella.tscn"),
    preload("res://minigames/memorice/scenes/almeja_basura.tscn"),
    preload("res://minigames/memorice/scenes/almeja_salmon.tscn"),
    preload("res://minigames/memorice/scenes/almeja_perla.tscn")
]
Items:
  1. Camarón (Shrimp)
  2. Zapatilla (Shoe)
  3. Lata (Can)
  4. Gusano (Worm)
  5. Alga (Seaweed)
  6. Plástico (Plastic)
  7. Botella (Bottle)
  8. Basura (Trash)
  9. Salmón (Salmon)
  10. Perla (Pearl)

Key Code Examples

Grid Generation

func _generar_tablero():
    var lista_instancias = []
    for escena in escenas:
        lista_instancias.append(escena.instantiate())
        lista_instancias.append(escena.instantiate())  # Duplicate for pair

    lista_instancias.shuffle()

    var columnas = 4
    var separacion = Vector2(65, 60)
    var filas = ceil(float(lista_instancias.size()) / columnas)
    var ancho_tablero = columnas * separacion.x
    var alto_tablero = filas * separacion.y
    var pantalla_centro = get_viewport_rect().size / 2
    var inicio = pantalla_centro - Vector2(ancho_tablero / 2, alto_tablero / 2)
    inicio += Vector2(30, 100)  # Offset for UI

    for i in range(lista_instancias.size()):
        var almeja = lista_instancias[i]
        var fila = i / columnas
        var col = i % columnas
        almeja.position = inicio + Vector2(col * separacion.x, fila * separacion.y)
        almejas_container.add_child(almeja)
4-column grid with 65px horizontal and 60px vertical spacing.

Initial Preview System

func mostrar_y_cerrar_inicialmente(almejas):
    bloquear_todas(true)

    # Open all clams
    for almeja in almejas:
        if almeja.has_method("abrir"):
            almeja.anim_sprite.play("abrir")
            almeja.abierta = true

    await get_tree().create_timer(5.0).timeout

    # Close all clams
    for almeja in almejas:
        if almeja.has_method("cerrar"):
            almeja.cerrar()

    bloquear_todas(false)
5-second preview period before gameplay begins.

Match Verification Logic

func _on_almeja_abierta(almeja):
    if not juego_iniciado or is_paused or comparando:
        return
        
    sfx_abrir.play()

    if primera_seleccion == null:
        primera_seleccion = almeja
    elif segunda_seleccion == null and almeja != primera_seleccion:
        segunda_seleccion = almeja
        comparando = true
        bloquear_todas(true, [primera_seleccion, segunda_seleccion])
        _verificar_pareja()

func _verificar_pareja():
    bloquear_todas(true)
    await get_tree().create_timer(0.1).timeout

    if primera_seleccion.objeto_id == segunda_seleccion.objeto_id:
        # Match found
        sfx_acierto.play()
        await get_tree().create_timer(0.6).timeout
        sfx_mas_puntos.play()

        _mostrar_texto_flotante(primera_seleccion.global_position, "+100", Color(0, 1, 0))
        puntos += 100
        actualizar_puntaje()
        await get_tree().create_timer(0.8).timeout

        if is_instance_valid(primera_seleccion): primera_seleccion.queue_free()
        if is_instance_valid(segunda_seleccion): segunda_seleccion.queue_free()

        await get_tree().process_frame

        if almejas_container.get_child_count() == 0:
            mostrar_victoria()

    else:
        # No match
        sfx_error.play()
        await get_tree().create_timer(0.4).timeout
        sfx_menos_puntos.play()

        _mostrar_texto_flotante(primera_seleccion.global_position, "-50", Color(1, 0, 0))
        puntos = max(puntos - 50, 0)
        actualizar_puntaje()
        await get_tree().create_timer(1.0).timeout

        if is_instance_valid(primera_seleccion): await primera_seleccion.cerrar()
        if is_instance_valid(segunda_seleccion): await segunda_seleccion.cerrar()
        
        await get_tree().create_timer(0.8).timeout

        if puntos == 0:
            mostrar_game_over()

    # Reset selections
    primera_seleccion = null
    segunda_seleccion = null
    comparando = false
    bloquear_todas(false)

Blocking System

func bloquear_todas(bloquear: bool, except: Array = []):
    for almeja in almejas_container.get_children():
        if almeja in except:
            continue
        almeja.bloqueada = bloquear
Prevents clicking during animations and comparisons.

Floating Text Feedback

var texto_flotante_escena = preload("res://minigames/memorice/scenes/texto.tscn")

func _mostrar_texto_flotante(pos, texto, color):
    var txt = texto_flotante_escena.instantiate()
    add_child(txt)
    txt.mostrar(pos, texto, color)
Visual feedback appears at click position showing points gained/lost.

Audio System

Memorice features rich audio feedback:
@onready var musica_fondo = $MusicaFondo
@onready var sfx_abrir = $SFX_AbrirAlmeja
@onready var sfx_acierto = $SFX_Acierto
@onready var sfx_error = $SFX_Error
@onready var sfx_menos_puntos = $SFX_menos_puntos
@onready var sfx_mas_puntos = $SFX_mas_puntos
Sound Effects:
  • Abrir: Clam opening sound
  • Acierto: Match success tone
  • Error: Mismatch buzzer
  • Mas Puntos: +100 points celebration
  • Menos Puntos: -50 points warning

Pause Audio Handling

func pause_game():
    musica_fondo.stream_paused = true
    sfx_abrir.stream_paused = true
    sfx_acierto.stream_paused = true
    sfx_error.stream_paused = true
    sfx_menos_puntos.stream_paused = true
    sfx_mas_puntos.stream_paused = true
All audio pauses/resumes with game state.

Victory Conditions

if almejas_container.get_child_count() == 0:
    mostrar_victoria()

func mostrar_victoria():
    _procesar_monedas_finales()
    $UI/GameOverPanel/Title.text = "¡Ganaste!"
    $UI/GameOverPanel/score.text = "Puntos: %d" % puntos
    $UI/GameOverPanel/CoinsEarned.text = "Monedas obtenidas: +%d" % last_coins_gained
    panel.visible = true
Victory occurs when all clam pairs removed from container.

Game Over Conditions

if puntos == 0:
    mostrar_game_over()

func mostrar_game_over():
    _procesar_monedas_finales()
    $UI/GameOverPanel/Title.text = "¡Fin del Juego!"
    $UI/GameOverPanel/score.text = "Puntos: %d" % puntos
    $UI/GameOverPanel/CoinsEarned.text = "Monedas obtenidas: +%d" % last_coins_gained
    panel.visible = true
Game over when points reach 0 from incorrect matches.

Clam Component Structure

Each clam (almeja) is an individual scene with:
  • objeto_id: String identifying item type
  • bloqueada: Boolean preventing interaction
  • abierta: Boolean tracking open/closed state
  • anim_sprite: AnimatedSprite2D with “abrir” animation
Required Signals:
signal almeja_abierta(almeja)
Required Methods:
func abrir() -> void
func cerrar() -> void

Screen Configuration

DisplayServer.window_set_size(Vector2i(480, 800))
DisplayServer.screen_set_orientation(DisplayServer.SCREEN_PORTRAIT)
Taller portrait mode (480x800) to accommodate 5-row grid.

Strategic Depth

Memorice rewards different strategies: Conservative: Open clams slowly, prioritizing accuracy (preserves points) Aggressive: Rapid clicking to gather information (risks point loss) Systematic: Open by rows/columns for organized memory (balanced approach) The -50 point penalty adds tension without being punishing, as perfect play yields +1000 points (10 matches × 100).

Nyuron Color

Another memory-focused sequence game

Minigames Overview

Return to all minigames

Build docs developers (and LLMs) love