🤔 Para Refletir : "Deus ajuda quem cedo farma." - Gui (Lummie)

Recriando Jogos Antigos no Game Maker Studio 1.4

Membro Membro
Postagens
161
Bravecoins
661
Fala pessoal, tudo bem? Recentemente eu me propus a um pequeno desafio, para testar minhas habilidades como programador. Eu estava jogando um game no emulador DOSBox que marcou muito minha infância, o Hocus Pocus, desenvolvido pela Apogee em 1994 para o MS-DOS. Enquanto eu jogava, cheguei à conclusão: Eu consigo recriar a primeira fase deste jogo no Game Maker! Pois bem, assim eu dei início a este projeto. É assim que ele está ficando:


Como podem ver, eu ainda não coloquei nenhum inimigo, nem as chaves, nem os tesouros que você coleta para aumentar o seu High Score. O HUD também é apenas "ilustrativo" até o presente momento.

Todos os Assets que consegui foram encontrados no site The Spriters Resource. Não usei nenhuma forma de emulação nem copiei o código fonte do título original, tudo o que fiz foi jogar, testar, e tentei replicar às mecânicas e física o mais próximo possível ao original, tudo à "olho nu". Caso você não conheça este jogo (e eu não te culpo), é possível jogar à versão Shareware online, através deste LINK.

Recomendo que vá lá e faça um comparativo com o vídeo demonstrado acima.

Minha intenção é utilizar deste espaço para publicar recriações de "primeiras fases" de jogos antigos. Quando eu tiver uma build completa de um projeto, deixarei aqui o link do executável para que qualquer um possa jogá-lo.
 
Última edição:
Vi no youtube uma gameplay desse jogo e vi a sua e achei bem legal e até simples para remasterizar.
Se vc for reproduzir o mesmo será plataforma?
Desejo sucesso no seu projeto e que de tudo certo.
 
Vi no youtube uma gameplay desse jogo e vi a sua e achei bem legal e até simples para remasterizar.
Se vc for reproduzir o mesmo será plataforma?
Desejo sucesso no seu projeto e que de tudo certo.
O objetivo é recriar o mais próximo ao original, sem nenhum compromisso em torná-lo "necessariamente" melhor. Assim que a primeira fase for concluída, disponibilizo o link para download aqui. Depois posso tentar fazer o mesmo com outros jogos, por exemplo, tenho vontade de recriar a primeira Dungeon do The Legend of Zelda para o NES.
 
Última edição:
Achei a iniciativa magnífica! É uma das melhores formas de praticar as habilidades. Fiquei até com vontade de fazer alguma coisa desse tipo, também, pra ver se desenferrujo o meu C# na Unity.
 
O Projeto do Hocus Pocus está praticamente pronto! O mapa já foi finalizado, com todos os itens devidamente posicionados e o HUD funcionando como deveria... A única coisa que falta é criar os inimigos. Estou muito satisfeito com o resultado até agora, mal posso esperar para disponibilizar o link quando tudo finalmente estiver concluído.

 
Última edição:
Hey @DougMR , estava aqui pensando com meu botões: vou dar umas ideias de jogos antigos.

Aí o espertoníldo aqui teve a brilhante ideia de buscar "arcade games 1980" no Google e, só de olhar a variedade, já fiquei cansado, rs!

Segue nessa força bro, sucesso!!!
 
Hey @DougMR , estava aqui pensando com meu botões: vou dar umas ideias de jogos antigos.

Aí o espertoníldo aqui teve a brilhante ideia de buscar "arcade games 1980" no Google e, só de olhar a variedade, já fiquei cansado, rs!

Segue nessa força bro, sucesso!!!
Até mesmo eu tenho tantas ideias de possíveis candidatos que acabo me perdendo 😂
Eu queria muito recriar a 1ª Dungeon do Legend of Zelda, mas também tenho muita vontade de recriar a primeira fase do Wolfenstein 3D, porque além de ele também ser um jogo da Apogee para o MS-DOS, seria muito interessante utilizar as funções d3d do Game Maker para criar o mesmo efeito de raycasting. Eu ainda não me decidi, mas também não vou recusar sugestões para projetos futuros, caso tenham.
O que eu posso dizer com o que estou aprendendo do projeto atual é: subestimamos demais os jogos clássicos pela simplicidade, mas apenas depois de tentar recriá-los do zero é que aprendemos a apreciar à genialidade no designe deles.
 

O Projeto do Hocus Pocus finalmente está concluído! Segue abaixo o link para download do executável:

>>LINK<<

Devo deixar claro que minha build não está "perfeita", mas como demonstrado no vídeo acima, é possível concluí-la sem demasiados problemas. Eu também não pretendo gastar tempo demais num único projeto, afinal, existem diversos outros jogos que pretendo recriar na engine do Game Maker. Espero que gostem do resultado do meu trabalho, até o próximo projeto!
 
Última edição:
Até mesmo eu tenho tantas ideias de possíveis candidatos que acabo me perdendo 😂
Eu queria muito recriar a 1ª Dungeon do Legend of Zelda, mas também tenho muita vontade de recriar a primeira fase do Wolfenstein 3D, porque além de ele também ser um jogo da Apogee para o MS-DOS, seria muito interessante utilizar as funções d3d do Game Maker para criar o mesmo efeito de raycasting. Eu ainda não me decidi, mas também não vou recusar sugestões para projetos futuros, caso tenham.
O que eu posso dizer com o que estou aprendendo do projeto atual é: subestimamos demais os jogos clássicos pela simplicidade, mas apenas depois de tentar recriá-los do zero é que aprendemos a apreciar à genialidade no designe deles.
Minha vontade era de tentar criar um game a lá Crusader of Centy do Mega Drive. Se tivesse as manhãs eu faria pq acho o game animal
 
Minha vontade era de tentar criar um game a lá Crusader of Centy do Mega Drive. Se tivesse as manhãs eu faria pq acho o game animal
Eu não lembrava desse jogo por nome, mas aí procurei um gameplay e na hora o reconheci. Era um joguinho com gráficos bem avançados para a época, eu lembro de ficar impressionado do protagonista ter sprites com animações diferentes para todas as 8 direções.
 
E aí galerinha, tudo certo?

Pois bem, agora, com um pouco mais de tempo livre, achei que seria uma boa oportunidade para retornar a este quadro, o "Recriando jogos Antigos no Game Maker 1.4".

Eu estava na dúvida entre The Legend of Zelda (NES) e Wolfenstein 3D (MS-DOS), mas decidi focar no "TLoZ", já que por este ser um jogo com perspectiva top down 2D, será um projeto mais simples, que concluirei mais rapidamente. Wolfenstein ficará para uma próxima.

Enfim, quais serão os objetivos desse projeto?

1 - Recriar o mapa da primeira Dungeon, respeitando o posicionamento de todos os itens, inimigos e NPC's;
2 - Por este ser um jogo de console (NES - Nintendo Entertainment System), além de termos suporte a comandos de teclado, também será possível jogar com um joystick X-Input (controle original de X-Box ou compatível);
3 - Recriar todas as mecânicas de gameplay, ex.: ao usar a espada tendo o valor máximo de HP um projétil será disparado, inimigos causam "meio" coração de dano, etc.

No jogo original, é possível entrar na 1ª Dungeon já tendo posse de alguns itens chave. Mas como eles não são necessários para a conclusão da mesma, serão ignorados.

Quais assets serão utilizados?

Todos os assets gráficos utilizados neste projeto foram obtidos no The Spriters Resource.
8366.png
8376.png

8381.png

21189.png
31806.png
32134.png
119278.png
168096.png

Eu poderia muito bem usar a imagem inteira do mapa para criar o level dentro do editor do Game Maker, mas como a intenção é recriar o jogo o mais próximo ao original, usarei a imagem apenas como referência e posicionarei os tiles manualmente.

Claramente, por este ser apenas um remake da primeira Dungeon, muitos assets serão ignorados. Para ser mais específico, os
assets "mínimos" que precisarei para concluir o level serão apenas:

INIMIGOS:
blade trap
keese
stalfos
gel
goriya
wallmaster
aquamentus

ITENS(quantia, sendo "rand" um valor "randômico", dropado aleatóriamente por inimigos):
chave pequena(6)
bússola(1)
mapa(1)
bumerangue(1)
arco(1)
container de coração(1)
fragmento da triforce(1)
fada(rand)
relógio(rand)
rúpia(rand)
bomba(rand)
"recarga" de coração(rand)

Como de costume, continuarei postando sobre o meu progresso, conforme o desenvolvimento deste projeto. Assim que estiver pronto, disponibilizarei um link para download em minha página do Itch.io.

Caso tenham perdido à oportunidade, segue abaixo o link para download de meu projeto anterior nesta série, um remake da primeira fase de "Hocus Pocus", para MS-DOS: Hocus Pocus (1st Level Remake)

Até mais ver ;)
 
Última edição:
Irei usar esse conteúdo como fonte de estudo! Já que, tenho a intenção de recriar Fumiko no Game Maker, vai cair como uma luva. Muito obrigado!
Valeu, @Aleth728 , fico grato em ser útil!

Pois bem, o que temos até agora?
Untitled.gif

*O mapa já foi devidamente recriado;
*Foram implementados movimento, colisão com paredes e animações do jogador andando;
*A câmera se move fluidamente ao transitar por entre as salas.

Por que a câmera está posicionada de tal forma, mostrando um pedaço da sala acima? É um bug?
Não, este espaço eventualmente será ocupado pelo HUD (Head-Up Display), como demonstrado abaixo, num print do jogo original:

Legend_of_Zelda_NES.PNG


O que precisa ser corrigido?
Alguns tiles precisam ter a profundidade arrumada, como por exemplo as portas, que atualmente são sobrepostas pelo sprite do jogador.

Códigos utilizados (observação - o código de movimento eventualmente será atualizado para dar suporte ao controle de Xbox):

Código:
///"step event" para o objeto do jogador

//MOVIMENTO E COLISÃO
if keyboard_check(vk_up) //Cima
{
    sprite_index=spr_player_up;
    if !place_meeting(x,y-2,obj_collision)
    {
        image_speed=0.1;
        y-=1.5;
    }
}
else if keyboard_check(vk_down) //Baixo
{
    sprite_index=spr_player_down;
    if !place_meeting(x,y+2,obj_collision)
    {
        image_speed=0.1;
        y+=1.5;
    }
}
else if keyboard_check(vk_left) //Esquerda
{
    sprite_index=spr_player_left;
    if !place_meeting(x-2,y,obj_collision)
    {
        image_speed=0.1;
        x-=1.5;
    }
}
else if keyboard_check(vk_right) //Direita
{
    sprite_index=spr_player_right;
    if !place_meeting(x+2,y,obj_collision)
    {
        image_speed=0.1;
        x+=1.5;
    }
}
else
    image_speed=0;

Código:
///"end step event" para o objeto do jogador

//CÂMERA
view_xview=lerp(view_xview,obj_player.x div 256*256,0.08); //Seguir jogador horizontalmente
view_yview=lerp(view_yview,obj_player.y div 176*176 - 64,0.08); //Seguir jogador verticalmente
 
Última edição:
Está ficando interessante essa recriação do TLOZ do Nintendinho no GameMaker. Estou curioso para saber como vai ser a parte dos inimigos. A parte da profundidade dos tiles em relação ao jogador é bem simples de resolver, só é levada a questão da organização das camadas de cada elemento do cenário.

Continue assim. Tá ficando show de bola! 👏👏👏
 
Está ficando interessante essa recriação do TLOZ do Nintendinho no GameMaker. Estou curioso para saber como vai ser a parte dos inimigos. A parte da profundidade dos tiles em relação ao jogador é bem simples de resolver, só é levada a questão da organização das camadas de cada elemento do cenário.

Continue assim. Tá ficando show de bola! 👏👏👏
Fico feliz que esteja gostando do resultado, @DanTheLion !

De fato, corrigir a profundidade dos tiles não foi muita dor de cabeça, ao contrário do que foi desenhar os corações no HUD, já que diferente de outros jogos, cada ponto de dano em TLoZ equivale a "meio" coração.

Sendo assim, por mais que você inicie a campanha com 3 corações, na prática o jogo conta como 6 pontos de vida.

Então, como eu fiz para saber qual "metade" do coração eu desejo desenhar no HUD?

O Game Maker possui um operador chamado "mod", que funciona como uma "divisão", mas ao invés de te dar o resultado da divisão entre dois valores, ele retorna apenas o valor após a casa decimal... Já que todo número par ao ser divido por dois dá "0" após a casa decimal, temos um método para diferenciar quais partes do coração desejamos desenhar dependendo do valor do HP do jogador.

O código de exibição dos corações no HUD ficou assim:
Código:
///"Draw Event" do objeto do HUD

for(i=0;i<global.player_max_HP/2;i++)//corações (valor máximo de HP)
    draw_sprite(spr_empty_heart,0,view_xview+176+(i*8),view_yview+48);

for(i=0;i<global.player_HP;i++)//corações (exibir HP atual)
{
    if i mod 2==0
        SPR=spr_heart_A;
    else
        SPR=spr_heart_B;      

    draw_sprite(SPR,0,view_xview+176+(i*4),view_yview+48);
}

E este é o resultado In-Game:

O que precisa ser corrigido agora?
Bom, como podem ver, apesar do "Blade Trap" já infligir dano ao jogador, ele ainda não se comporta como deveria.
Além disso, o player não sofre knock back ao receber dano, ele deveria ser empurrado levemente na direção oposta.

Enfim, de pouquinho em pouquinho estamos chegando cada vez mais perto!
É impressionante como apenas adicionando algumas animações, música e efeitos sonoros, nosso projeto se aproxima ainda mais do original.

Espero que estejam gostando do resultado, eu particularmente estou bem empolgado! :)
 
Última edição:
É interessante fazer esse tipo de recriação justamente pra entender um pouco das limitações de design dos jogos mais antigos. Apesar que hoje em dia usamos ferramentas infinitamente superiores ao que se tinha nos anos 80 ou 90.

Se realmente gostar dessa área, tem gente que estuda sobre emulação ou engenharia reversa (ou até outros métodos) que poderiam ajudar a recriar da maneira mais fiel e precisa o possível tais jogos, apesar de que não deve ser esse o objetivo, né?

Só digo que é interessante, hoje em dia temos ports abertos de jogos como Super Mario 64, Driver 2, Tomb Raider, entre vários outros por que a galera se atentou a conseguir o melhor resultado possível, então é uma área legal de se estudar.

Outra coisa é que vi um canal na gringa que recria jogos de maneiras inusitadas: https://www.youtube.com/@CodyCantEatThis/videos

Talvez isso possa servir como inspiração. Continue o excelente trabalho!
 
Última edição:
É interessante fazer esse tipo de recriação justamente pra entender um pouco das limitações de design dos jogos mais antigos. Apesar que hoje em dia usamos ferramentas infinitamente superiores ao que se tinha nos anos 80 ou 90.
[...]
Fala @Rafael_Sol_MAKER ! Obrigado pelo seu comentário!

Sim, o meu objetivo não é necessariamente recriar esses jogos tão fielmente que não seja possível diferenciá-los um do outro, nem mesmo fazer melhorias muito contrastantes às mecânicas originais.

Não sei se conseguirei explicar, mas existe algo de muito satisfatório/divertido em tentar recriar os jogos que marcaram minha infância a "olho nu", apenas fazendo uso do meu atual conhecimento de programação e sem fazer muitas pesquisas no Google. Deve ser o equivalente para aqueles cartunistas que desenham seus personagens com os traços de outro artista, apenas para homenageá-lo.


1a2cda96b6d3753bf10f70c6d019b322ba76ad9a23e7787ab3a89b9b1cc07fa8_1.jpg

Existe um nível de apreciação por estes jogos que só é obtido quando você tenta recriá-los respeitando a visão do desenvolvedor original... Você começa a se fazer perguntas, tentando entender o que o levou a tomar certas decisões...

* "Por que você precisa 'coletar' a espada numa caverna, ao invés de iniciar o jogo com ela já equipada?";

* "Por que você gasta rúpias ao atirar com o arco, ao invés de ter um item coletável dedicado às flechas?".


E é apenas ao tentar responder essas perguntas que você começa a perceber que muita coisa que antes parecia um simples "erro" de designe, ou apenas uma limitação da época, foi na verdade algo bem mais intencional do que antes imaginado.

Quanto ao canal que você mencionou, lembro de já ter visto alguns vídeos dele, principalmente os da série de remakes de jogos 2D para 3D. Ele é um rapaz muito talentoso ^^

Talvez não seja uma má ideia fazer algo semelhante num projeto futuro... Um remake com um "spin" :)
 
Oi galera!

Aqui estão as atualizações de hoje:

* Item "espada de madeira" incluso / jogador agora é capaz de atacar inimigos;
* Inimigo "Stalfos" incluso;
* Knock Back (ser empurrado) ao receber dano;
* Blocos "empurráveis" inclusos;
* Algoritmo comportamental de "Blade Trap" atualizado.

Códigos utilizados:
Código:
///OBJETO - BLADE TRAP

///"Create Event"
//----------------
H_ATK=false;
V_ATK=false;
HSPD=0;
VSPD=0;
returningX=false;
returningY=false;

///"Alarm0 Event"
//----------------
returningY=true;

///"Alarm1 Event"
//----------------
returningX=true;

///"Step Event"
//----------------
if x>view_xview
and x<view_xview+256
and y>view_yview+64
and y<view_yview+240 //checar se está dentro da tela
{
    if instance_exists(obj_player)
    {
        if (distance_to_point(obj_player.x+8,y)<1  //detecção vertical do Player
        and point_distance(x,y,x,ystart)<=1
        and returningY==false
        and returningX==false
        and H_ATK==false)
        {
            alarm[0]=room_speed;
            if HSPD==0
            {
                V_ATK=true;
                if obj_player.y>y
                    VSPD=2;
                else
                    VSPD=-2;
            }
        }
        else if (distance_to_point(x,obj_player.y+8)<1  //detecção horizontal do Player
        and point_distance(x,y,xstart,y)<=1
        and returningY==false
        and returningX==false
        and V_ATK==false)
        {
            alarm[1]=room_speed;
            if VSPD==0
            {
                H_ATK=true;
                if obj_player.x>x
                    HSPD=2;
                else
                    HSPD=-2;
            }
        }      
    }
   
    if !place_meeting(x,y+VSPD,obj_collision)
    and !place_meeting(x,y+VSPD,obj_blade_trap)
        y+=VSPD;
    else
        VSPD=0;
       
    if !place_meeting(x+HSPD,y,obj_collision)
    and !place_meeting(x+HSPD,y,obj_blade_trap)
        x+=HSPD;
    else
        HSPD=0;      
}

//retornar
if returningY==true
{
    if y!=ystart
        move_towards_point(x,ystart,0.5);
    else
    {
        V_ATK=false;
        returningY=false;
        speed=0;
    }
}
if returningX==true
{
    if x!=xstart
        move_towards_point(xstart,y,0.5);
    else
    {
        H_ATK=false;  
        returningX=false;
        speed=0;
    }
}
Código:
///OBJETO - STALFOS

///"Create Event"
//------------------
hurt=false;
X_SPD=0;
Y_SPD=0;
HP=2;

image_speed=0.05;

direction=choose(90,270,180,0);
alarm[0]=room_speed*(irandom_range(2,4));

///"Alarm0 Event"
//------------------
if instance_exists(obj_player)
{
    player_DIR=point_direction(x,y,obj_player.x,obj_player.y) div 90*90;
    direction=choose(90,270,180,0,player_DIR);
}
else
    direction=choose(90,270,180,0,player_DIR);
alarm[0]=room_speed*(irandom_range(2,4));

///"Alarm1 Event"
//------------------
hurt=false;
image_speed=0.05;
X_SPD=0;
Y_SPD=0;

///"Step Event"
//------------------
if x>view_xview
and x<view_xview+256
and y>view_yview+64
and y<view_yview+240 //checar se está dentro da tela
{
    if hurt==false
        speed=0.5;
    else
        speed=0;
}
else
{
    x=xstart;
    y=ystart;
    HP=2;
    speed=0;
}

//colisão
if place_meeting(x+1,y,obj_collision)
or place_meeting(x-1,y,obj_collision)
or place_meeting(x,y+1,obj_collision)
or place_meeting(x,y-1,obj_collision)
{
    if X_SPD==0
    and Y_SPD==0
        direction=choose(90,270,180,0);
}

//receber dano
if place_meeting(x,y,obj_atk_mask_parent)
{
    if hurt==false
    {
        audio_play_sound(sfx_enemy_dmg,3,false);
           
        image_speed=0;
        HP-=1;
       
        DMG=instance_nearest(x,y,obj_atk_mask_parent);
        kb_dir=round((point_direction(x,y,DMG.x,DMG.y)/90))*90;
        with DMG
            instance_destroy();
       
        if kb_dir==0
        or kb_dir==360
            X_SPD=-3;
        if kb_dir==180
            X_SPD=3;
        if kb_dir==90
            Y_SPD=3;      
        if kb_dir==270
            Y_SPD=-3;
             
        alarm[1]=10;      
        hurt=true;
    }
}

if place_meeting(x,y,obj_sword_proj)
{
    if hurt==false
    {
        audio_play_sound(sfx_enemy_dmg,3,false);
           
        image_speed=0;
        HP-=1;
       
        DMG=instance_nearest(x,y,obj_sword_proj);
        kb_dir=round((point_direction(x+8,y+8,DMG.x,DMG.y)/90))*90;
       
        TL=instance_create(x+8,y+8,obj_sword_proj_part);
        TR=instance_create(x+8,y+8,obj_sword_proj_part);      
        BL=instance_create(x+8,y+8,obj_sword_proj_part);
        BR=instance_create(x+8,y+8,obj_sword_proj_part);              
       
        TL.sprite_index=spr_sword_proj_part_TL;
        TR.sprite_index=spr_sword_proj_part_TR;      
        BL.sprite_index=spr_sword_proj_part_BL;
        BR.sprite_index=spr_sword_proj_part_BR;
       
        TL.direction=135;
        TR.direction=45;
        BL.direction=225;
        BR.direction=315;      
       
        with DMG
            instance_destroy();
       
        if kb_dir==0
        or kb_dir==360
            X_SPD=-3;
        if kb_dir==180
            X_SPD=3;
        if kb_dir==90
            Y_SPD=3;      
        if kb_dir==270
            Y_SPD=-3;
             
        alarm[1]=10;      
        hurt=true;
    }
}

if !place_meeting(x+X_SPD,y,obj_collision)
    x+=X_SPD;
if !place_meeting(x,y+Y_SPD,obj_collision)  
    y+=Y_SPD;
   
//morrer
if HP<=0
{
    instance_create(x,y,obj_enemy_death);
    instance_destroy();
}

///"End Step Event"
//------------------
while place_meeting(x+1,y,obj_collision)
{
    x-=0.1;
    if X_SPD==0
    and Y_SPD==0
        direction=choose(90,270,180,0);  
}
while place_meeting(x-1,y,obj_collision)
{
    x+=0.1;
    if X_SPD==0
    and Y_SPD==0
        direction=choose(90,270,180,0);  
}
while place_meeting(x,y+1,obj_collision)
{
    y-=0.1;
    if X_SPD==0
    and Y_SPD==0
        direction=choose(90,270,180,0);  
}
while place_meeting(x,y-1,obj_collision)
{
    y+=0.1;
    if X_SPD==0
    and Y_SPD==0
        direction=choose(90,270,180,0);  
}

///"Draw Event"
//------------------
if hurt==false
    draw_self();
else
    draw_sprite(spr_stalfos_dmg,image_index,x,y);
 
Voltar
Topo