Yamix Posted January 11, 2018 at 06:19 PM Report #608904 Posted January 11, 2018 at 06:19 PM (edited) Olá, estou aqui de novo, estava desenvolvendo um novo programa, to fazendo tudo sozinho, to conseguindo aprender muita coisa, mas não consigo sair de um problema, to tentando resolver já faz mais de 2 horas, mas não consigo, então venho aqui pedir ajuda. To usando a váriavel Tecla como se fosse um readkey: Tecla := Readkey; E isso ao mesmo tempo que me ajuda com os movimentos da nave, me atrapalha. 1) Se eu apertar J, eu não posso me mexer até que o tiro atravesse o mapa, queria fazer com que minha nave possa se mexer, mesmo que ela tinha disparado um tiro. Eu tinha conseguido fazer com que meu tiro se movesse enquanto eu tivesse fazendo a minha nave andar, mas esse não é o meu objetivo. 2) Se eu pressionar o J e não soltar o dedo, meu boneco trava, e fica disparando tiros até que todos os meus J pressionados acabem. Queria fazer minha nave andar enquanto tem um tiro passando pelo mapa. E se tem como "trancar" o meu J, fazendo com que ele funcione uma única vez, até que o tiro atravesse o mapa. Const TiroV = '"'; // Desenho do tiro na Vertical TiroH = '='; // Desenho do tiro na Horizontal NaveFre = 'v'; // Desenho da nave em cada angulo. NaveAtr = '^'; NaveDir = '>'; NaveEsq = '<'; Var Tecla : Char; CooldownTiro : Boolean; TiroX,TiroY : Integer; NaveX,NaveY : Integer; NaveDX,NaveDY : Integer; // Direcao em que minha nave está mirando. TrajetoTiroX,TrajetoTiroY,ContadorTiro : Integer; // Direcao em que o tiro ira passar pelo mapa. Procedure MoveNave; Begin // PAREDE INVISIVEL EM Y = 50; NAVE DESCE UMA LINHA If (Tecla = 's') or (Tecla = 'S') then Begin NaveY := NaveY + 1; If NaveY >= 50 then NaveY := NaveY - 1; NaveDX := 0; NaveDY := 0; NaveDY := NaveDY + 1; GoToXY(Navex,NaveY); If NaveDY > 0 then Write(NaveFre); Delay(50); ClrScr; End; // PAREDE INVISIVEL EM Y = 1; NAVE SOBE UMA LINHA If (Tecla = 'w') or (Tecla = 'W') then Begin NaveY := NaveY - 1; If NaveY = 1 then NaveY := NaveY + 1; NaveDX:=0; NaveDY:=0; NaveDY:= NaveDY - 1; GoToXY(NaveX,NaveY); If NaveDY < 0 then Write(NaveAtr); Delay(50); ClrScr; End; // PAREDE INVISIVEL EM X = 1; NAVE AVANCA 1 CARACTERE PARA FRENTE If (Tecla = 'a') or (Tecla = 'A') then Begin NaveX := NaveX - 1; If NaveX = 1 then NaveX := NaveX + 1; NaveDY := 0; NaveDX := 0; NaveDX := NaveDx - 1; GoToXY(NaveX,NaveY); If NaveDX < 0 then Write(NaveEsq); Delay(50); ClrScr; End; // PAREDE INVISIVEL EM X = 65; NAVE VOLTA 1 CARACTERE PARA TRAS If (Tecla = 'd') or (Tecla = 'D') then Begin NaveX := NaveX + 1; If NaveX >= 65 then NaveX := NaveX - 1; NaveDY := 0; NaveDX := 0; NaveDX := NaveDX + 1; GoToXY(NaveX,NaveY); If (NaveDX > 0) then Write(NaveDir); Delay(50); ClrScr; End; End; Procedure MoveTiro; Begin If (Tecla = 'J') or (Tecla = 'j') and (CooldownTiro = False) then Begin TiroX := NaveX; TiroY := NaveY; NaveParada; // TIRO ESQUERDA If (NaveDX < 0) then Begin For TrajetoTiroX := TiroX downto 1 do Begin GoToXY(NaveX,NaveY); Write(NaveEsq); TiroX := TiroX - 1; GoToXY(TiroX,TiroY); Write(TiroH); Delay(10); ClrScr; End; If (TrajetoTiroX = 1) then Begin ContadorTiro:= 2; While (ContadorTiro > 0) do Begin NaveParada; Dec(ContadorTiro); Delay(1000); ClrSCr; If (ContadorTiro = 0) then CooldownTiro := False; End; End; End; // TIRO DIREITA If (NaveDX > 0) then Begin For TrajetoTiroX := TiroX to 65 do Begin GoToXY(NaveX,NaveY); Write(NaveDir); TiroX := TiroX + 1; GoToXY(TiroX,TiroY); Write(TiroH); Delay(10); ClrScr; End; If (TrajetoTiroX = 65) then Begin ContadorTiro:= 2; While (ContadorTiro > 0) do Begin NaveParada; Dec(ContadorTiro); Delay(1000); ClrSCr; If (ContadorTiro = 0) then CooldownTiro := False; End; End; End; // TIRO CIMA If (NaveDY < 0) then Begin For TrajetoTiroY := TiroY downto 1 do Begin GoToXY(NaveX,NaveY); Write(NaveAtr); TiroY := TiroY - 1; GoToXY(TiroX,TiroY); Write(TiroV); Delay(10); ClrScr; End; If (TrajetoTiroY = 1) then Begin ContadorTiro:= 2; While (ContadorTiro > 0) do Begin NaveParada; Dec(ContadorTiro); Delay(1000); ClrSCr; If (ContadorTiro = 0) then CooldownTiro := False; End; End; End; // TIRO BAIXO If (NaveDY > 0) then Begin For TrajetoTiroY := TiroY to 50 do Begin GoToXY(NaveX,NaveY); Write(NaveFre); TiroY := TiroY + 1; GoToXY(TiroX,TiroY); Write(TiroV); Delay(10); ClrScr; End; If (TrajetoTiroY = 50) then Begin ContadorTiro:= 2; While (ContadorTiro > 0) do Begin NaveParada; Dec(ContadorTiro); Delay(1000); ClrSCr; If (ContadorTiro = 0) then CooldownTiro := False; End; End; End; NaveParada; End; End; Tudo o que eu tentei não deu certo 😞 Edited January 11, 2018 at 06:38 PM by Gabriel Gomes Alinhar;
nunopicado Posted January 11, 2018 at 11:58 PM Report #608909 Posted January 11, 2018 at 11:58 PM Assim de repente, esse problema é um pouco mais complexo do que isso. Para fazeres duas operações em simultaneo, terás provavelmente de usar multi-threading, que está longe de ser 'coisa de iniciante'. Precisarias que o CPU do computador se encarregasse de dar seguimento ao movimento da nave/tiro, enquanto o UI fica livre para continuares a controlar o resto. "A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!" > Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.
pwseo Posted January 12, 2018 at 12:48 PM Report #608913 Posted January 12, 2018 at 12:48 PM Existe uma hipótese de «simular» esse multithreading, mas não sei se a standard library em Pascal possui tudo o que é necessário... Basicamente, é necessário ter uma forma de ler o estado do teclado sem interromper o programa (ou seja, em vez de utilizar ReadKey que bloqueia até que algo seja pressionado, precisamos de uma função que «olhe para o teclado» num dado momento e nos diga se determinada tecla está pressionada e devolva logo o controlo ao programa). Tendo isto, o programa principal poderá consistir num ciclo que executa X vezes por segundo (p ex 30) e que em cada iteração verifica que teclas estão a ser pressionadas e actualiza o ecrã de acordo com o estado geral das coisas. Continua a não ser, de todo, algo para um iniciante... mas evita a complexidade das threads, e pode ser até mais intuitivo nalguns aspectos. 1 Report
Yamix Posted January 12, 2018 at 04:22 PM Author Report #608918 Posted January 12, 2018 at 04:22 PM Vou postar como está meu código agora, ele não está do jeito que eu quero, mas quando eu aprender a como fazer isso já vou poder começar a por meu projeto em prática. program tiro; uses crt; Const TiroV = '"'; TiroH = '='; NaveFre = 'v'; NaveAtr = '^'; NaveDir = '>'; NaveEsq = '<'; Var Comecar,Tecla : Char; Jogando,CooldownTiro : Boolean; TiroX,TiroY : Integer; NaveX,NaveY : Integer; NaveDX,NaveDY : Integer; TrajetoTiroX,TrajetoTiroY,ContadorTiro : Integer; Procedure Cenario; var CX,CY,CX1,CY1 : Integer; Begin CX := 1; CY := 12; CX1 := 1; CY1 := 12; TextColor(15); // CENARIO X DE CIMA For CX := CX to 80 do Begin GoToXY(CX,CY); Write('#') End; // CENARIO Y DA ESQUERDA For CY := CY to 50 do Begin GoToXY(1,CY); Write('#') End; // CENARIO X DE BAIXO For CX1 := CX1 to 80 do Begin GoToXY(CX1,CY); Write('#') End; // CENARIO Y DA DIREITA For CY1 := CY1 to 50 do Begin GoToXY(CX,CY1); Write('#') End; End; Procedure Start; Begin WriteLn('Deseja jogar? Pressione T'); ReadLn(Comecar); If (Comecar = 't') or (comecar = 'T') then Begin Jogando := true; ClrScr; Cenario; TextColor(9); GoToXY(NaveX,NaveY); Write(NaveFre); End; End; Procedure MoveNave; Begin TextColor(9); // APERTAR S MOVE PARA BAIXO If (Tecla = 's') or (Tecla = 'S') then Begin GoToXY(NaveX,NaveY); ClrEol; NaveY := NaveY + 1; // PAREDE INVISIVEL EM Y = 50; While (NaveY = 50) do NaveY := NaveY - 1; // CONFIGURA DIRECAO EM QUE A NAVE ESTARA MIRANDO NaveDX := 0; NaveDY := 0; NaveDY := NaveDY + 1; GoToXY(Navex,NaveY); If (NaveDY > 0) then Write(NaveFre); End; // APERTAR W MOVE PARA CIMA If (Tecla = 'w') or (Tecla = 'W') then Begin GoToXY(NaveX,NaveY); ClrEol; NaveY := NaveY - 1; // PAREDE INVISIVEL EM Y = 12; If NaveY = 12 then NaveY := NaveY + 1; NaveDX:=0; NaveDY:=0; NaveDY:= NaveDY - 1; GoToXY(NaveX,NaveY); If NaveDY < 0 then Write(NaveAtr); End; // SE APERTAR A MOVE PARA ESQUERDA If (Tecla = 'a') or (Tecla = 'A') then Begin GoToXY(NaveX,NaveY); ClrEol; NaveX := NaveX - 1; // PAREDE INVISIVEL EM X = 1; If NaveX = 1 then NaveX := NaveX + 1; // CONFIGURA DIRECAO EM QUE A NAVE ESTARA MIRANDO NaveDY := 0; NaveDX := 0; NaveDX := NaveDx - 1; GoToXY(NaveX,NaveY); If NaveDX < 0 then Write(NaveEsq); End; // SE APERTAR D MOVE PARA DIREITA If (Tecla = 'd') or (Tecla = 'D') then Begin GoToXY(NaveX,NaveY); ClrEol; NaveX := NaveX + 1; // PAREDE INVISIVEL EM X = 65; If NaveX = 80 then NaveX := NaveX - 1; // CONFIGURA DIRECAO EM QUE A NAVE ESTARA MIRANDO NaveDY := 0; NaveDX := 0; NaveDX := NaveDX + 1; GoToXY(NaveX,NaveY); If (NaveDX > 0) then Write(NaveDir); End; End; Procedure NaveParada; Begin If (Keypressed = false) Then Begin Cenario; TextColor(9); // DIRECAO PARA BAIXO If (NaveDY > 0) then Begin GoToXY(NaveX,NaveY); Write(NaveFre); End; // DIRECAO PARA CIMA If (NaveDY < 0) then Begin GoToXY(NaveX,NaveY); Write(NaveAtr); End; // DIRECAO PARA DIREITA If (NaveDX > 0) then Begin GoToXY(NaveX,NaveY); Write(NaveDir); End; // DIRECAO PARA ESQUERDA If (NaveDX < 0) then Begin GoToXY(NaveX,NaveY); Write(NaveEsq); End; End; End; Procedure MoveTiro; Begin If (Tecla = 'J') or (Tecla = 'j') and (CooldownTiro = False) then Begin TiroX := NaveX; TiroY := NaveY; // TIRO ESQUERDA If (NaveDX < 0) and (CooldownTiro = False) then Begin For TrajetoTiroX := TiroX downto 2 do Begin GoToXY(TiroX,TiroY); ClrEol; TiroX := TiroX - 1; GoToXY(TiroX,TiroY); Write(TiroH); End; If (TrajetoTiroX = 2 ) then Begin ContadorTiro:= 2; While (ContadorTiro > 0) do Begin NaveParada; GoToXY(3,60); TextColor(4); WriteLn(' Tiro esta em cooldown : ',ContadorTiro,' segundo(s).'); Dec(ContadorTiro); Delay(1000); If (ContadorTiro = 0) then CooldownTiro := False; GoToXY(3,60); ClrEol; End; End; End; // TIRO DIREITA If (NaveDX > 0) and (CooldownTiro = False) then Begin For TrajetoTiroX := TiroX to 79 do Begin GoToXY(TiroX,TiroY); ClrEol; TiroX := TiroX + 1; GoToXY(TiroX,TiroY); Write(TiroH); End; If (TrajetoTiroX = 79) then Begin ContadorTiro:= 2; While (ContadorTiro > 0) do Begin NaveParada; GoToXY(3,60); TextColor(4); WriteLn(' Tiro esta em cooldown : ',ContadorTiro,' segundo(s).'); Dec(ContadorTiro); Delay(1000); If (ContadorTiro = 0) then CooldownTiro := False; GoToXY(3,60); ClrEol; End; End; End; // TIRO CIMA If (NaveDY < 0) and (CooldownTiro = False) then Begin For TrajetoTiroY := TiroY downto 13 do Begin GoToXY(TiroX,TiroY); ClrEol; TiroY := TiroY - 1; GoToXY(TiroX,TiroY); Write(TiroV); End; If (TrajetoTiroY = 13) then Begin ContadorTiro:= 2; While (ContadorTiro > 0) do Begin NaveParada; GoToXY(3,60); TextColor(4); WriteLn(' Tiro esta em cooldown : ',ContadorTiro,' segundo(s).'); Dec(ContadorTiro); Delay(1000); If (ContadorTiro = 0) then CooldownTiro := False; GoToXY(3,60); ClrEol; End; End; End; // TIRO BAIXO If (NaveDY > 0) and (CooldownTiro = False) then Begin For TrajetoTiroY := TiroY to 49 do Begin GoToXY(TiroX,TiroY); ClrEol; TiroY := TiroY + 1; GoToXY(TiroX,TiroY); Write(TiroV); End; If (TrajetoTiroY = 49) then Begin ContadorTiro:= 2; While (ContadorTiro > 0) do Begin NaveParada; GoToXY(3,60); TextColor(4); WriteLn(' Tiro esta em cooldown : ',ContadorTiro,' segundo(s).'); Dec(ContadorTiro); Delay(1000); If (ContadorTiro = 0) then CooldownTiro := False; GoToXY(3,60); ClrEol; End; End; End; End; End; Begin HighVideo; NaveX:=31; NaveY:=32; ClrScr; Start; Cenario; Repeat Tecla := Readkey; MoveNave; NaveParada; MoveTiro; Until (Jogando = False) or (Tecla = 'y') or (Tecla = 'Y'); end. Só queria fazer minha nave poder se mexer, enquanto tem um tiro atravessando o mapa, estou muito frustado tentei várias coisas já e não funciona.
Yamix Posted January 13, 2018 at 06:41 PM Author Report #608927 Posted January 13, 2018 at 06:41 PM (edited) Consegui, refiz meus códigos varias dezenas de vezes e consegui chegar nisso.. Program Nave_GTest; // POR FAVOR SE FOR USAR DE CREDITOS AOS GABRIEL GOEMS xD // NAO DORMI DIREITO, POR DOIS DIAS PARA CHEGAR NISSO AQUI. Uses Crt; Var NaveX,NaveY : Integer; // COORDENADAS X E Y DA NAVE. TiroX,TiroY : Integer; // COORDENADAS X E Y DO TIRO. Tecla : Char; // IDENTIFICARA A TECLA APERTADA. Atirou : Boolean; // IDENTIFICARA SE O PLAYER ATIROU OU NAO. Procedure Tiro; Begin GoToXY(TiroX,NaveY-TiroY); // FAZ COM QUE A BALA SUBA NUMA VELOCIDADE DE 1 EM 1. TextColor(Yellow); // EX: NaveY-TiroY -> 24 - 1 = 23 - 1 = 22... Write('"'); // DESENHO DO TIRO If (TiroY>1) then Begin // ENQUANTO O TIRO ESTA SUBINDO GoToXY(TiroX,NaveY-TiroY+1); // ISSO FAZ O PAPEL DO CRLSCR, Write(' '); // E SUBSTITUI O DESENHO DO TIRO POR UM ESPACO EM BRANCO. End; End; Procedure MoverNave; Begin TextColor(LightBlue); // DESENHO DA NAVE. GoToXY(NaveX,NaveY); Write('^'); // FAZ O PAPEL DE CLRSCR E APAGA O ULTIMO LUGAR POR ONDE A NAVE PASSOU. GoToXY(NaveX-1,NaveY); // A ESQUERDA. Write(' '); GoToXY(NaveX+1,NaveY); // A DIREITA. Write(' '); End; Begin NaveX:=1; NaveY:=24; TiroY:= 0; TiroX:= 0; ClrScr; GoToXY(1,NaveY); ReadKey; Repeat; If (TiroY>=NaveY) then Begin GoToXY(TiroX,1); // QUANDO O TIRO CHEGA NO TOPO ISSO APAGA O TIRO. Write(' '); // SEM USAR O CLRSCR. TiroY:=0; // COM ISSO, O PROGRAMA RODA APENAS COM 1 LOOP, NECESSARIO PARA QUE O "THREAD" FUNCIONE Atirou:=False; // SE O TIRO CHEGOU NO TOPO ENTAO PODE ATIRAR DE NOVO. If (TiroY = 24) then Begin // IMPEDE QUE A ANIMACAO DO TIRO DE UM BUG QUE FAZ COM O QUE O TIRO VAI PARAR NA GoToXY(TiroX,TiroY); // COORDENADA Y DA NAVE. Write(' '); End; End; Tecla := 'T'; // FAZ COM QUE A NAVE NAO TRAVE SE O PLAYER APERTOU UMA TECLA DE ANIMACAO VARIAS VEZES. If (KeyPressed = True) then Tecla:= ReadKey; If (NaveX=1) and (Tecla=#75) then NaveX:= NaveX + 1; // PAREDE INVISIVEL EM X=1. If (NaveX=79) and (Tecla=#77) then NaveX := NaveX - 1; // PAREDE INVISIVEL EM X = 79 Case Tecla Of #75: NaveX:=NaveX-1; // MOVE A NAVE PARA A ESQUERDA. #77: NaveX:=NaveX+1; // MOVE A NAVE PARA A DIREITA. ' ': Begin // MUDA O STATUS DA VARIAVEL ATIROU PARA TRUE Atirou:=true; // E COMECA O PROCEDURE TIRO. Tiro; End; End; If (TiroY<NaveY) and (Atirou=True) then Tiro; // FAZ COM QUE EU POSSA ME MEXER, MESMO ENQUANTO A BALA ESTÁ CAMINHANDO MoverNave; // FAZ COM QUE OS TIROS SAIAM DA COORDENADA X DA NAVE. If (TiroY=0) then TiroX:= NaveX; // LIMITA 1 TIRO POR VEZ E FAZ A BALA SUBIR DE 1 EM 1. If (Atirou=True) then TiroY:=TiroY+1; // CONTROLA O TEMPO DE MOVIMENTO DA NAVE E DO TIRO. Delay(20); Until (Tecla=#27); // SE A TECLA APERTADA FOR ESC, ACABA O JOGO. End. Agora vou descansar, e mais tarde irei fazer com que minha nave possa atirar e/ou se mexer para qualquer direção. Edited January 13, 2018 at 06:45 PM by Gabriel Gomes
BHAMF Posted January 13, 2018 at 11:27 PM Report #608936 Posted January 13, 2018 at 11:27 PM (edited) Já presenciei um problema parecido... Consegui resolver da seguinte maneira: [...] uses Crt; var alvo : integer; procedure movimento; begin repeat if (keypressed = #75) or (keypressed = #77) then begin //seta esquerda e direita [movimentos da nave] //faz o movimento da nave e rapidamente volta movimentoDoTiro; end else begin if (keypressed = #74) or (keypressed = #106) then begin movimentoDoTiro; end else begin //caso não seja continua com o jogo normal //papel de fundo passando end; end; until (keypressed = #27) end; procedure movimentoDoTiro; var X1, Y1 : integer; begin for I := 1 to alvo do begin //A variável alvo é favorável caso o tiro atinja o fim do mapa ou outra nave. gotoxy(x, y+1); //variáveis teste X1 := WhereX; //Adiciona a posição de X À variável X1 Y1 := WhereY; //Adiciona a posição de Y À variável Y1 if alvoTest = true then begin gotoxy(X1,Y1); clreol; //apaga a linha end; if (keypressed) then begin movimento; end; end; end; begin movimento; end. Aviso que coloquei este código sem pensar muito nas outras variáveis como o papel de fundo passando, vida da nave, e essas coisas assim. Sendo assim, pode conter alguns bugs no código acima, mas a questão principal parece ter sido resolvida. Estou meio sem tempo agora pra pensar direito, mas mesmo assim espero ter ajudado. 🙂 boa sorte aí no projeto, talvez eu volte com um código melhor mais tarde. 20:23 | 13/01/2018 (Horário de Brasília) Edited January 14, 2018 at 12:04 AM by BHAMF 1 Report Brenio Hallison A.M. Filho
Yamix Posted January 13, 2018 at 11:36 PM Author Report #608937 Posted January 13, 2018 at 11:36 PM Toda ajuda é bem vinda, obrigado pela sua dica BHAMF, parece funcionar muito bem.. possivelmente vou usar ela em algum momento 😄
thoga31 Posted January 14, 2018 at 04:17 AM Report #608938 Posted January 14, 2018 at 04:17 AM Voltei a fazer login após meses sem vir ao P@P depois de o @nunopicado me ter falado que havia por aqui um tópico que abordava um potencial caso de multithreading com Pascal. Parece-me que o assunto já ficou resolvido para já, mas fica aqui um tópico que eu criei acerca do assunto há uns anos atrás onde eu proponho um método que simula multithreading: https://www.portugal-a-programar.pt/forums/topic/50251-simular-multithreading-em-pascal/ Cumprimentos, thoga31 😉 Knowledge is free!
Yamix Posted January 14, 2018 at 01:33 PM Author Report #608943 Posted January 14, 2018 at 01:33 PM (edited) Thoga31, eu vi esse tópico enquanto quebrava cabeça pensando em algo para simular o multithread, tenho até aqui anotado num bloco de notas a forma que tu utilizas, eu usei sua dica sobre o delay, pode ver que está até no programa, obrigado por vir aqui me ajudar! 😄 Estou a rondar o passado do fórum sempre, e você, nunopicado e Pwseo são os mais ativos, até onde eu vi. Isso é realmente muito bom, obrigado por ajudar nós principiantes sempre! 😄 Abraços. Gabriel Gomes. Edited January 14, 2018 at 01:35 PM by Gabriel Gomes 1 Report
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now