Giter VIP home page Giter VIP logo

super-mario-kart's Introduction

Süper Mario Kart

Authors: Diego Royo, Víctor Martínez and Javier Giménez

Süper Mario Kart is an C++ implementation of Super Mario Kart, a kart racing video game developed and published by Nintendo for the Super Nintendo Entertainment System in 1992. The purpose of this project is to understand the basic components of a real videogame. The authors do not aim at any commercial profit and release the source code for the general public under GPLv3 license.

Yoshi racing in Rainbow Road Mario racing in Donut Plains
Normal gameplay in Bowser Castle Chaos! Lots of items!

Available circuits

Donut Plains 1

See details

Donut Plains 1

Mario Circuit 2

See details

Mario Circuit 2

Ghost Valley 1

See details

Ghost Valley 1

Bowser Castle 1

See details

Bowser Castle 1

Rainbow Road

See details

Rainbow Road

1. Game download

Pre-built binaries (Windows-only) of Süper Mario Kart are available for download in any of the following:

1.1. Tips for playing

  • You can take a look at the controls (and change them as you like!) in the "Controls" section of the Start Menu.

  • Each vehicle has different properties. Please note that they also have some drawbacks, so choose carefully!

    • Yoshi and Peach: Greater acceleration, to reach its maximum speed earlier.
    • Koopa and Toad: Higher turning speed, to take better turns.
    • Bowser and Donkey Kong: Higher top speed and higher weight to hit other runners.
    • Mario and Luigi: Balanced vehicles, with a mixture of these factors.
  • If you start to accelerate when the second traffic light comes on, you will start the race with a little boost of speed. Be careful, because if you accelerate prematurely, your motor may overheat too much and you could be incapacitated for a few seconds.

  • Getting coins is more important than it seems. Each increases your maximum speed, which makes a difference. There is a limit of 10 coins per player.

  • By turning for a while you can drift, allowing you to make sharp turns without problem. Using the drift key (C by default) you can enter "drift mode" much earlier, giving you more control over your turns. This is especially useful in 100cc and 150cc modes.

  • If you take a very tight curve and think you are turning too much, you can press the skid key (C by default) one or many times. The jump causes you to stop turning for a while, allowing you to open up your trajectory a bit before continuing to skid.

  • On more complicated circuits, such as Bowser Castle 1 or Rainbow Road, it is a good idea to brake in curves. We also have to be careful with some objects, like the mushroom, since the speed boost can be difficult to control.

2. Building Süper Mario Kart

2.1. Prerequisites

We have tested the game in Windows 10 and some Linux distributions. For building your own executable file, the following are needed.

C++11 Compiler

We use MinGW32 (posix) 8.1.0 by MinGW-W64 for Windows and GCC 7.5.0 for Linux.

Simple and Fast Multimedia Library (SFML)

We use SFML 2.5.1 for graphics generation and audio playback.

Open Audio Library (OpenAL)

We use OpenAl as cross-platform API for 3D audio.

2.2. Building

Clone the repository:

git clone https://github.com/vmbatlle/super-mario-kart SMK

We provide a Makefile to build the source and link needed libraries statically (Windows only). Please make sure you have installed all required dependencies (see section 2). Execute:

cd SMK/src
make -j8 release  # change -j option according to your CPU threads

This will create a bin folder with compiled files and the executable super_mario_kart in the parent folder.

3. Creating new circuits

Some utils are provided for semi-automatic generation of new circuits. For this process the following requiremenst are expected:

  • Python 3.X interpreter.
  • Python libraries: Numpy 1.16.1 and Matplotlib 3.1.3. Other versions may work.
  • Assets of the circuit: with and without floor objects.
  • (Optional) Add new land params to generate_map.py. Land types for Donut Plains, Mario Circuit, Ghost Valley, Bowser Castle and Rainbow Road are already implemented as invocation flags.
  • (Optional) Add wall sprites next to the scripts.
  • Background and final lap music, if not yet present.
  • Edge material, for texture out of circuit bounds.
  • Sky back and front assets.

Steps

  1. Prepare plain circuit asset (without floor objects), and execute:
python ./generate_map.py -f PATH_TO_ASSET -w WALL_TYPE_FILE -t CIRCUIT_TYPE

Then, base.txt will be generated next to the asset file.

Example:

python ./generate_map.py \
    -f ../assets/circuit/mario_circuit_2/base.png \
    -w walls.png \
    -t mario_circuit
  1. Find the circuit asset with floor objects, and proceed:
python ./generate_floor_objects.py -f PATH_TO_ASSET -o OBJECTS_FILE

Then, objects.txt will be generated in the same folder.

Example:

python ./generate_floor_objects.py \
    -f ../assets/circuit/mario_circuit_2/objects.png \
    -o floor_objects.png
  1. Add the new option to the game menu, at racemanager.h:
CIRCUIT_DISPLAY_NAMES = {"name_of_the_circuit"};
CIRCUIT_ASSET_NAMES = {"path/to/circuit/folder"};

Example: Note: some aspects of the game (menus, etc.) are made with five circuits in mind (not six), so it's easier to swap your new circuit for an old one.

constexpr const int NUM_CIRCUITS = 5;

const std::array<std::string, NUM_CIRCUITS> CIRCUIT_DISPLAY_NAMES = {
    "donut plains 1",  "mario circuit 2", "ghost valley 1",
    "bowser castle 1", "rainbow road",
};

const std::array<std::string, NUM_CIRCUITS> CIRCUIT_ASSET_NAMES = {
    "assets/circuit/donut_plains_1", "assets/circuit/mario_circuit_2",
    "assets/circuit/ghost_valley_1", "assets/circuit/bowser_castle_1",
    "assets/circuit/rainbow_road",
};
  1. Rebuild target (see section 2)

  2. First time the new circuit is loaded gradient.txt and position.txt will be generated from the base.txt file.

Please, keep the folder tree as follows:

  • assets/
    • circuit/
      • circuit_name/
        • base.png
        • base.txt
        • edge.png
        • final_lap.ogg
        • gradient.txt
        • music.ogg
        • objects.png
        • objects.txt
        • position.txt
        • sky_back.png
        • sky_front.png

super-mario-kart's People

Contributors

diegoroyo avatar javibite avatar vmbatlle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

super-mario-kart's Issues

Mejora del uso de objetos por parte de la IA

Ahora los objetos los usa con un random, se puede añadir una puntuación de "cómo de bueno sería usar este objeto ahora mismo" y hacer que sea más probable usarlo en momentos buenos

Si la IA está mucho tiempo en un área, hacer TP.

Para asegurar que la IA no se queda bloqueada durante mucho tiempo, p. ej. contra una pared; comprobar si no ha salido de un área (p. ej. de 3x3 tiles) durante un tiempo. Utilizar la misma primitiva que cuando se salgan del circuito (TP con/sin Lakitu).

El estado del jugador Uncontrolled no se quita en el estado RaceEnd

Explicación más detallada:

  1. En la última vuelta, el player character es golpeado por un rayo, lo que lo coloca en el estado uncontrolled.
  2. El player character termina la vuelta (y por tanto la carrera) con la propia inercia de su vehículo.
  3. En el estado RaceEnd no se lleva cuenta de los estados de los jugadores, por lo que nunca se popea el estado Uncontrolled y todos los jugadores afectados por el rayo (incluido el PlayerCharacter) se quedan quietos.

Lakitu "Wrong direction" no para sonido si te caes yendo marcha atrás.

Versión del bug 2b2538a:

Por ejemplo, en la senda arcoiris. Si te caes mientras está presente el Lakitu de dirección errónea el sonido SFX no se detiene.

Para hacer un medio-fix, he puesto que a partir de ahora NO se puedan reproducir en bucle (loop = true) dos SFX iguales. Aún con todo, deber arreglar lo del pitido porque sigue sonando cuando Lakitu te devuelve con caña de pescar.

Guardar controles en un fichero

Al cargar el juego se leen todos los controles de un fichero. Si este no existe o hay algun problema al leerlo, se sustituye por los defaults

Ausencia de reset de color de estrella al terminar la carrera

Si al terminar la carrera hay un jugador que le está afectando el cambio de color por la estrella, este cambio de color se mantiene en pantallas posteriores (por ejemplo, en el estado congratulations donde se muestra a los corredores en el podio)

El color de la estrella (y bueno, creo que todos los efectos de items en general) deberían ser quitados cuando el player character termine cualquier carrera, para evitarnos este tipo de problemas.

Añadir música adicional fuera de la carrera.

No tiene por qué ser diferente para cada pantalla, podría ser una música de fondo en bucle idéntica siempre que no se esté corriendo. Lo importante es que no se quede en silencio el juego.

Parece que los jugadores salen del estado SMALL al mismo tiempo

Parece que el tiempo de animación SMALL no está bien ajustado en función de la posición de los jugadores en el momento de recibir el rayo. Si es posible acceder a la posición desde driver.cpp:234, valdría con multiplicar SPEED_DOWN_DURATION por un escalar en función de la posición.

Nota: ¿por qué estos tiempos no coinciden?

animator.small(SPEED_DOWN_DURATION + SPEED_DOWN_DURATION);
pushStateEnd(DriverState::SPEED_DOWN, StateRace::currentTime + SPEED_DOWN_DURATION);

Choque de jugadores cuando están en el aire

Las comprobaciones de colisión solo se deberían hacer si los dos objetos (jugadores, items, etc.) están a una altura parecida (si se chocan A y B, abs(h_a - h_b) < valor_pequeño)

Problemas visuales menores con el champiñón y GUI

@JaviBite

  • Al usar un champiñón sale un efecto de velocidad. Si te caes al vacío con el champiñón en efecto, el efecto perdura mientras estás quieto.
  • El efecto de velocidad no parece una textura del juego al estar poco "pixelado".
  • Si terminas una carrera con un objeto y luego empiezas otra, no se resetea la GUI de objetos. Sale que tienes ese objeto en la GUI, pero no lo puedes usar porque no lo tienes realmente. (mirar el resto de la GUI también)
  • Si coges una caja de objetos y usas el objeto al momento, la animación de "objeto aleatorio" de la GUI sigue reproduciéndose (podemos hacer dos cosas: o evitar que el usuario use objetos mientras está en "objeto aleatorio" o parar en ese momento la animación de la GUI)

@diegoroyo

  • Los jugadores en el minimapa no tienen el origen bien puesto cuando estan en modo SMALL
  • Las sombras de los jugadores pequeños no se ven pequeñas en el circuito Map::getDriverDrawables(...)

Información de tipo de terreno y farvision de IA en los mapas

Añadir al fichero objects.txt de cada mapa:

  • Información de los tres tipos de terreno: terreno normal, terreno lento, terreno outer
    • (opcional) Emplear esta información para las partículas de derrape (hay un documento "Sobre los circuitos" en Drive)
    • (opcional) Emplear esta información para generar nuevas partículas al conducir sobre hierba
    • (opcional) Emplear esta información para introducir nuevos SFX (mapas como ghost_valley_1 o derrapar/conducir por cualquier terreno de cualquier mapa)
    • Emplear esta información para el efecto EffectDrown (tanto para objetos como para jugadores que caigan al agua). Ver qué hacemos con la lava
  • Información sobre el farvision de la IA (para 50cc, 100cc, 150cc), para que tome las curvas correctamente

Añadir una sombra debajo de los objetos con height > 0

Hay que tener en cuenta tres cosas:

  • Necesitamos sprite de sombra
  • Todas las funciones getXXXDrawables(...) de map.cpp pueden devolver un segundo drawable que sea la sombra, situado en la misma posición que el jugador y con altura 0 (asegurar que la sombra se pinta detrás del jugador)
  • Hay que tener en cuenta el caso especial donde es el propio jugador el que salta, necesitando añadir otro caso especial a la función Driver::getDrawable() (ahora podría devolver dos drawables)
  • Ciertos wallobjects (otros drivers, thwomps, etc.)
  • Driver del player character
  • Lakitu

Problemas con Lakitu

  • Lakitu puede dejar a algún NPC en la misma posición exacta de donde estaba bloqueado (añadir un random a la posición, aumentar el numero de tiles del gradiente que camina?)
  • La variable onLakitu del driver puede no resetearse después de que te recoja Lakitu (y por tanto, no puedes caer)
  • Si terminas la carrera y te caes al vacío en el estado RaceEnd, te quedas quieto
    • Imagino que Lakitu está ocupado con la animación de la bandera final
    • El personaje pasa de DriverControlType::PLAYER a DriverControlType::AI_GRADIENT
    • El personaje aparece en la posición donde lo dejaría Lakitu, en el suelo, pero no se puede mover
  • Puedes empezar la carrera en el aire (si terminas la carrera anterior cayéndote? no me he fijado en los pasos para reproducirlo)
  • Relacionado con lo anterior, después de jugar varias carreras es posible que el recolocamiento por lakitu funcione mal. Me ocurrió al jugar varias carreras seguidas, llegar a la senda arco íris y caerme, Lakitu siempre me devolvía a la posición inicial (intentaré reproducirlo con más detalles)

Hacer compatible animación 'fall' con TP instantáneo con Lakitu.

En la línea driver.cpp:413 se invoca a la animación de DriverAnimator::fall() pero no es visible a causa de la relocalización instantánea de Lakitu. Se deben también retesar los efectos adversos y power-ups, tanto del estado del jugador como del sprite.

Quizás se podría hacer que el animator haga al jugador pequeño, luego se pase a fundido a negro la pantalla del jugador (parte superior), en ese momento se llama a Driver::relocateToNearestGoodPosition() y finalmente se quita el fundido a negro.

Escalar la GUI con la resolución

Relacionada con #15

En game.cpp:86 se debería llamar a los métodos setWindowSize() o setScale() necesarios para que todos los elementos de la GUI sean escalados. Se puede asumir que el tamaño "normal" del juego es 512x448 píxeles y por tanto, la escala que se debería aplicar a todos los sprites es:

BACKGROUND_WIDTH = 512.0f
scale = window.getSize().x / BACKGROUND_WIDTH

Monedas

Por ahora el jugador gana monedas, pero no pierde monedas en ningún momento:

Debería perder monedas:

  • Al entrar en modo HIT (chocarse con un oil slick, caparazones verdes, etc.)
  • [?] Al entrar en modo SMASH (thwomps)
  • [?] Al chocar contra otros jugadores (puedo encargarme yo)

  • (opcional) Animación de GUI para ganar monedas y perder monedas

Mejoras del estado Demo

  • Arreglar el hecho de que la IA lanza objetos al pulsar 1-7
  • Fijar la cámara en algún corredor (añadir algún icono de "cámara fija"?)
  • Modo "primera persona" (en lugar de seguir a un corredor en la distancia, seguirlo de cerca)

`Segmentation fault` en Bowser Castle

Backtrace from GDB:

Thread 1 received signal SIGSEGV, Segmentation fault.
0x66b86358 in sf::Image::getPixel(unsigned int, unsigned int) const ()
   from C:\mingw810\i686-810-posix-dwarf-rt_v6-rev0\mingw32\mingw\bin\sfml-graphics-2.dll
(gdb) bt
#0  0x66b86358 in sf::Image::getPixel(unsigned int, unsigned int) const ()
   from C:\mingw810\i686-810-posix-dwarf-rt_v6-rev0\mingw32\mingw\bin\sfml-graphics-2.dll
#1  0x0044370c in Map::sampleAsset (asset=..., sample=...) at map/map.h:81
#2  0x004197c0 in Map::sampleMap (this=0x4b3e40 <Map::instance>, sample=...) at map/map.cpp:6
#3  0x00419cf1 in Map::mode7 (this=0x4b3e40 <Map::instance>, position=..., angle=-0.0132949613,
    fovHalf=0.5, clipNear=0.000500000024, clipFar=0.0450000018, size=..., perspective=true)
    at map/map.cpp:49
#4  0x0041bd39 in Map::circuitTexture (player=
    std::shared_ptr<Driver> (use count 5, weak count 0) = {...}, circuitTexture=...) at map/map.cpp:384   
---Type <return> to continue, or q <return> to quit---
#5  0x00428e4b in StateRace::draw (this=0xf37d328, window=...) at states/race.cpp:130
#6  0x004395ed in Game::run (this=0xf5fc80) at game.cpp:69
#7  0x0043a130 in main () at main.cpp:5

La música no se repite y acaba antes de las 5 vueltas

Efecto esperado:
La música debería permanecer reproduciéndose durante toda la carrera. Opcionalmente, modificar la pista reproducida durante la última vuelta por la correspondiente música acelerada.

Efecto actual:
La música termina a los 01' 40'' de juego (caso Mario Circuit 2).
La música termina a los 02' 54'' de juego (caso Donut Plain).
Etc.

Lakitu para fuera de límites

Por ahora todavía te deja en sitios raros y lleva velocidad mientras te tiene en el aire, ¿debería ser estático? ¿cuál es el mejor sitio al que devolver al jugador?

Efectos del salto pequeño/salto en rampa

Actualmente los saltos tienen algunos problemas:

  • En bowser castle 1, para 50cc o 100cc es imposible saltar la lava sin caerse
  • El salto para derrapar no funciona: al hacer un salto pequeño no se entra en modo derrape
  • #11

Propongo los siguientes cambios para los saltos con rampa, para que sean más cómodos para el jugador:

Al saltar:

  • El jugador no puede acelerar, pero tampoco se frena al no estar en contacto con el suelo
  • El jugador sigue pudiendo girar. Ahora mismo la cámara se ve muy quieta en los saltos, girar sin acelerar puede dar algo de control en el aire al jugador, aunque igual el jugador gira demasiado al caer al suelo.

Ya diréis qué opináis sobre estos cambios

La caída del rayo no afecta a la velocidad de los jugadores

Efecto esperado:
Cuando a un jugador (cualquiera) le cae un rayo, se debería frenar su aceleración y poner a 0 su velocidad angular, similar a un oil slick.

Efecto actual:
Al caer un rayo encima de un player character, este puede seguir girando/mantiene su velocidad angular, dando un menor efecto de ralentización y pérdida de control.

Comportamiento del power-up estrella ⭐

Comprobar si la estrella:

  • Hace inmune al jugador frente a terrenos lentos.
  • Hace al jugador invencible contra choques con objetos.
  • Tiene un efecto positivo para el jugador en caso de choque con otro.

  • La estrella debe hacerte invencible frente a rayos

Problemas con followedPath de lakitu

A veces tu followedPath no crece y solo tiene 1 elemento.

Observaciones:

  • Parece que se añaden cosas, el problema está al quitarlas (siempre se puede hacer print debugging)
  • A veces el bug se soluciona solo con parar el debugger, así que igual tiene que ver con el tiempo transcurrido

Gestor de música (idea)

Viendo que hay varios problemas al llamar directamente al sistema de audio desde cualquier sitio (issues #1 #2 #12 #13), propongo lo siguiente:

  • Modificar Audio::play(music) para que ponga las canciones en bucle correctamente
  • Añadir una capa por encima de Audio::play(music) para la música (situada donde sea), a la que le puedas indicar donde estas (en carrera, en el menu 1, menu 2, etc.) y suene la música correspondiente
  • Esta capa ha de pedirle a Map cual es la música del circuito acutal (tanto la normal como la de ir rápido)
  • Para el caso de la estrella, esta capa se encarga de pausar la música actual, hacer sonar la estrella, y cuando termine vuelve a sonar la música anterior. Si suena más de una estrella a la vez símplemente se resetea (por ello, la estrella debe ser música y no SFX)

No se si me dejo algún caso especial, ya diréis qué os parece y cómo nos encargamos de esto

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.