c# Pong program
Ahoj měl bych dotaz, zkoušel jsem si naprogramovat hru PONG na internetu jsem našel jakýsi návod jak jí naprogramovat tak, že vy ovládáte sebe pomocí myše ale hrajete proti "AI" měl bych otázku a to takovou, jak by se to mělo naprogramovat aby místo AI hrál druhý hráč na klávesách W - nahoru, S - dolu.
A ještě aby nahoře byla tabulka skore, která by počítala do 7 a poté by napsala Vyhrál hráč červený/modrý. Níže přikládám program, který zatím mám. Opravdu by se mi to hodilo a byl bych každýmu moc vděčný za pomoc.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Pong
{
public partial class Form1 : Form
{
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;
int ballSpeedX = 3;
int ballSpeedY = 3;
int gameTimeInterval = 1;
PictureBox picBoxPlayer, picBoxPlayer2, picBoxBall;
Timer gameTime;
Size sizePlayer = new Size(25, 100);
Size sizePlayer2 = new Size(25, 100);
Size sizeBall = new Size(20, 20);
public Form1()
{
picBoxPlayer = new PictureBox();//
picBoxPlayer2 = new PictureBox();//Initializes the PictureBoxes
picBoxBall = new PictureBox();//
gameTime = new Timer();//Initializes the Timer
gameTime.Enabled = true;//Enables the Timer
gameTime.Interval = gameTimeInterval;//Set the timer's interval
gameTime.Tick += new EventHandler(gameTime_Tick);//Creates the Timer's Tick event
InitializeComponent();
this.Width = SCREEN_WIDTH;
this.Height = SCREEN_HEIGHT;
this.StartPosition = FormStartPosition.CenterScreen;//opens the form in center of the screen
picBoxPlayer.Size = sizePlayer;//sets the size of the picturebox
picBoxPlayer.Location = new Point(picBoxPlayer.Width / 2, ClientSize.Height / 2 - picBoxPlayer.Height / 2);//sets it's location (centered)
picBoxPlayer.BackColor = Color.Blue;//fills the picturebox with a color
this.Controls.Add(picBoxPlayer);//adds the picture box to the form
picBoxPlayer2.Size = sizePlayer2;
picBoxPlayer2.Location = new Point(picBoxPlayer2.Width / 2, ClientSize.Height / 2 - picBoxPlayer2.Height / 2);
picBoxPlayer2.BackColor = Color.Red;
this.Controls.Add(picBoxPlayer2);
picBoxBall.Size = sizeBall;
picBoxBall.Location = new Point(ClientSize.Width / 2 - picBoxBall.Width / 2, ClientSize.Height / 2 - picBoxBall.Height / 2);
picBoxBall.BackColor = Color.Green;
this.Controls.Add(picBoxBall);
}
private void gameTime_Tick(object sender, EventArgs e)
{
picBoxBall.Location = new Point(picBoxBall.Location.X + ballSpeedX, picBoxBall.Location.Y + ballSpeedY);
gameAreaCollisions();//Checks for collisions with the form's border
padlleCollision();//Checks for collisions with the padlles
playerMovement();//Updates the player's position
player2Movement();//Updates the ai's position
}
private void gameAreaCollisions()
{
if (picBoxBall.Location.Y > ClientSize.Height - picBoxBall.Height || picBoxBall.Location.Y < 0)
{
ballSpeedY = -ballSpeedY;
}
else if (picBoxBall.Location.X > ClientSize.Width)
{
resetBall();
}
else if (picBoxBall.Location.X < 0)
{
resetBall();
}
}
private void resetBall()
{
picBoxBall.Location = new Point(ClientSize.Width / 2 - picBoxBall.Width / 2, ClientSize.Height / 2 - picBoxBall.Height / 2);
}
private void playerMovement()
{
if (this.PointToClient(MousePosition).Y >= picBoxPlayer.Height / 2 && this.PointToClient(MousePosition).Y <= ClientSize.Height - picBoxPlayer.Height / 2)
{
int playerX = picBoxPlayer.Width / 2;
int playerY = this.PointToClient(MousePosition).Y - picBoxPlayer.Height / 2;
//on click W player.Y++;
//on click S player.Y--;
picBoxPlayer.Location = new Point(playerX, playerY);
}
}
private void player2Movement()
{
if (ballSpeedX > 0)
{
picBoxPlayer2.Location = new Point(ClientSize.Width - (picBoxPlayer2.Width + picBoxPlayer2.Width / 2), picBoxBall.Location.Y - picBoxPlayer2.Height / 2);
}
}
private void padlleCollision()
{
if (picBoxBall.Bounds.IntersectsWith(picBoxPlayer2.Bo unds))
{
ballSpeedX = -ballSpeedX;
}
if (picBoxBall.Bounds.IntersectsWith(picBoxPlayer.Bou nds))
{
ballSpeedX = -ballSpeedX;
}
}
}
}
tak pohyb hráčů evidentně zajišťují player2movement a playerMovement. Player2Movement je počítaný jako AI, takže tam musíš změnit kód, aby nabíral ovládání z klávesnice.
Pokud řešíš počítání, tak to musíš implementovat do míst, kde se řeší "vypadení" z hřiště a následuje procedura "resetBall". Tam budeš muset připočítávat skóre nějakým dvěma proměnným, které můžeš vykreslovat na hřišti. Plus přidat kontrolu na dosažení 7 bodů.
ehm ono všude kde je player2 bylo původně AI, já jsem to pouze změnil jako první krok a dále jsem nedošel, zapomněl jsem to uvést :) A já právě vůbec nevím jak to napsat tak by se mi hodil nějaký příklad :)
Příklad konkrétně čeho?
jak to napsat jsem ztracený
Já bych ti klidně pomohl s konkrétními problémy, ale celé to za tebe fakt dělat nechci.
Jenže tu je problém, že já nemám vůbec představu o tom jak by to mělo vypadat a hledal jsem už i na angických forech
Prostě jenom zachytáváš stisk klávesy a podle toho s tím hýbeš nahoru nebo dolů.
Možno by si mal hľadať tu: www.devbook.cz
ale tu jsem to nenašel v c #
panebože! Ty lepíš kód, který nechápeš? Takto se přece neprogramuje!
je to program do školy
Tak o to víc by ses měl snažit sám. Zatím jsi jenom okopíroval kus kódu z webu.
ano jenže mě to programování nikdy moc nešlo a jde mi celkem o hodně a času zrovna také není mnoho :)
A jak dlouho máš ten úkol zadaný? Už to nějaký čas bude, že?
máme to už týden ale zatím jsme to dělali jen ve škole
Co jste zatím dělali ve škole? Vždyť tenhle kód je kompletně stažený z webu.
Je to zadaná práce pro jednotlivce, každý si na tom dělá sám
Za tu 1 hodinu ve škole jsem sám zvládl udělat pouze ty dvě "rakety"
Udělat? Stáhnout z webu. A hodinu nebo týden?
Hele přiznej si, že jsi na to do teď zvysoka kašlal a teď se na poslední chvíli snažíš zachránit, co se dá.
mám ještě dva týdny a programování máme jen jednou týdně tudíž 1hodinu. Ale chci to mít už dopředu abych to potom nehledal den před odevzdáním
Je to práce asi tak na hodinu. Ale nepočítej s tím, že to za tebe někdo bude dělat.
však si napiš postup (algoritmus) na papír, česky bez technických fines. Zjistíš, že to je úplně triviální.
načteš klávesu -> zjistíš jaká to je -> odpočítáš pozici úplně stejným stylem jako u player1 (Y nahoru nebo dolů).
Počty jsou přece taky easy (dokonce bych řekl, že úplně megatriviál): na začátku je skóre P1=0, P2=0. Na místě, kde se provádí test vypadení, uděláš P1++, resp. P2++ (podle toho, jestli míček vypadl vlevo (x<0), nebo vpravo. Následně zkontroluješ, zda je P1 nebo P2 větší než 6 a podle toho případně vypíšeš výsledek hry.
Tak jsem nakonec ten program začal od znova tak jak jsme to dělali ve škole a přidal jsem jednotlivé hráče do tříd. Pouze míček mi nešel nějak udělat a pohyb toho míčku a následnou kolizi s palkama a hrací plochou se mi nepodařilo vymyslet takže tu část programu jsem zkopíroval a upravil hodnoty do mého programu. Jenže je tady problém, že se míček pohybuje stále jedním směrem a mám takové tušení, že ani nereaguje na pálky. Uploadl jsem celý soubor na uloz.to tak pokud by někdo měl chvilku a chut byl bych mu moc vděčný kdyby mi řekl co tam je špatně.
Podařilo se mi nastavit to ovládání obou pálek na klávesnici.
Zde je odkaz:
pong-rar
Je naprostý nesmysl, aby jednotliví hráči byly dvě různé třídy. Pak je tam spousta menších chyb. Např. ten pohyb jedním směrem - ujisti se, že nemícháš X-ové souřadnice a Y-ový pohyb.
Dobře děkuji prošel jsem to a jedna souřadnice tam byla špatně ted už to funguje. Už mi zbývá pouze udělat to, aby ty pálky nevyjížděli z plochy. Oni se nezastaví dole na tom panelu ale prostě jedou dál a ještě jsem zjistil, že to nemá počítat "skore" ale počet kolikrát ty pálky ten míček odrazí např palka1 odrazí míček nahoře se objeví jedna letí to na palku 2 tak dkyž odrazí přičte se 2 a tak dále a v tom menu by měla být další možnost "rekord" která ukáže jaký byl nejvyšší počet pinknutí.
opravdu nikdo neví jak ošetřit to aby palky nevyjižděla z panelu a poté počítání počtu kolik bylo odrazeno ?
zkus se zamyslet, je to obojí víceméně o jednom řádku.
pálky musíš kontrolovat před překreslením zadaného pohybu, zda už nedosáhly určité Y-nové hranice (nahoře i dole, nezapomeň odečíst délku pálky)
počítání odpalů je taky jednoduché, stačí inkrementovat počitadla pokaždé, když se změní X-ový vektor pohybu (tj. směr pohybu vlevo se změní na pohyb vpravo a obráceně pro druhou pálku)
Já mám jakousi představu o tom jak by to mělo fungovat ale prostě nevím jak dát ten kod dohromady, furt mi to nejde
Tak sem napiš, co jsi zkoušel.
Ale ví, jen ses na to neptal. Psal jsi jenom, že ti to zbývá udělat.
Tak dnes mám poslední den a vůbec netuším jak ověřit to vyjíždění a počítání těch úderu od pálky to mi fakt nikdo neporadí ?
Prostě si vypočítáš, jestli by pálka byla mimo hrací pole, a pokud ne, tak s ní nepohneš.
Pokud jde o počítání úderů, tak v místě kde kontroluješ, jestli to nenarazilo do pálky, jenom přidáš počítadlo.
asi jsem opravdu hloupý ale nedokážu si to ani představit, koukám se i do toho druhého programu ale marně. Není to náhodou tohle ?
if (this.PointToClient(MousePosition).Y >= picBoxPlayer.Height / 2 && this.PointToClient(MousePosition).Y <= ClientSize.Height - picBoxPlayer.Height / 2)
{
int playerX = picBoxPlayer.Width / 2;
int playerY = this.PointToClient(MousePosition).Y - picBoxPlayer.Height / 2;
picBoxPlayer.Location = new Point(playerX, playerY);
Jak si to nedokážeš představit? Znáš pozici pálky? Znáš. Znáš velikost pálky? Znáš. Znáš výšku hracího pole? Znáš.
Jenom zjišťuješ, jestli horní hrana pálky nepřesáhne horní hranu pole, resp. dolní hrana pálky dolní hranu pole.
no to je jedno já se zeptám ve škole, takhle bych na to asi opravdu nepřišel
Tak trochu zapřemýšlej, na to stačí i matika z prvního stupně základní školy.
Tak to počítání jsem už zvládl už se to počítá, jen když mám tu pálku blbě napozicovanou tak se míček jakoby projede po té pálce a až potom odpalí a napočítá to třeba 30 ale to se stane jednou za čas takže to nevadí už mi zbývá jen to ověření
doufám, že se nehodláš živit programováním
to rozhodně ne ale to myslím, že už si poznal
není to žádný oficiální tak nevím v čem je problém od toho do té školy chodíme píšu, že to nevadí jelikož na to sám beztak nepříjdu
Ked micek prejede palku tak mas blbo niektory test if ktory testuje poziciu micu oproti pozicii palky. Mne sa nechce ten zdrojak studovat, to by mala byt tvoja robota si to skontrolovat ten test.
Program musis chapat, to sa neda len tak lepit a sem tam cosi menit co ta napadne.
To "projíždění" ošetříš tak, že při změně směru míčku při odrazu, si opravdu ověříš, že jde míč od pálky.
přišel jsem na to jak to udělat stačilo přidat:
micekSpeedY = -micekSpeedY;
to je nezmysel to ti teraz odraza blbym smerom.
také na to ted koukám .. sakra
Wikan ti pisal ze si mas kontrolovat pri tej kolizii ci je skutocne speedX kladna (>0) na levaj strane alebo zaporna (<0) na pravej strane, ak neni tak nerobis nic (nepricitavas pocet uderov ani neobracias smer speedX) ptz to by znamenalo ze si nahodou trafil situaciu ked si koliziu zistil 2x pri stejnom udere (uz si raz to speedX ototcil)
Na tu kolizi pálek to mám takto
Dávej to do tagu "code", to se jinak nedá číst! (touchwood)
No tak si ještě ověř, že se ten míček pohybuje správným směrem a je to.
ok děkuji vám všem moc za pomoc :)
to vyjíždění z toho panelu asi sám nezvládnu, jelikož tomu vůbec nerozumím jak to ověřit ale tak nevadí
Co je na tom nezvladnutelne?
if (picBoxMicek.Bounds.IntersectsWith(palka2.Bounds))
{
if(micekSpeedX < 0)
{
micekSpeedX = -micekSpeedX;
skore += 1;
label1.Text = skore.ToString();
}
}
{
if (picBoxMicek.Bounds.IntersectsWith(palka1.Bounds))
{
if(micekSpeedX > 0)
{
micekSpeedX = -micekSpeedX;
skore += 1;
label1.Text = skore.ToString();
}
}
ked to bude zle (naopak) tak prehodis <0 za >0 a >0 za <0
Tak osobně bych to dal ještě před "IntersectsWith".
Tak to je fuk, moze dat aj obe veci do jedneho if :)
Takhle jsem to myslel. A díky zkrácenému vyhodnocování to fuk není.
Do skoly to fuk je, tam sa nehra na optimalnost. Samozrejme ked clovek mysli optimalne tak da najprv jednoduchsi test, ale ten test boundaries bude tiez len par jednoduchych if ktore CPU zvladne za nanosekundy, a neni to v slucke ktora by zlozitost algoritmu zvysovala, je to zlozitost O(n) t.j. nepodstatne zaoberat sa par if. Ale ok ked chces extremne optimalizovat tak ma vyznam pozerat sa na poradie testov.
Ach jo. Výška herního pole je 100 px, výška pálky je 20 px. Pálka je 50px od horní hrany.
O kolik px se může pálka posunout nahoru? A o kolik px dolů?
no o 40, pokud to teda beru tak že 50px je uprostřed a 10px je směrem dolu a 10px směrem nahoru
Uff, zkus si to nakreslit. A ptal jsem se na dvě otázky.
no když je přímo uprostřed (50px) a má 20px tak 40px směrem dolu a 40px nahoru
Pokud auto stojí 1 m od zdi, myslí se tím snad vzdálenost zdi a poloviny auta?
no nechme to být to je jedno
OK, ty potřebuješ poradit, ne já.
problém přetrvává opravdu nikdo neví ?
Vždyť už jsi odpověď dostal. Co na ní nechápeš?
ano dostal ale stále nevím jak to napsat do toho programu, jaký příkaz použít
Uz sme ti napisali co je problem. Ked si nevies ani svoj vytvor zdebugovat, tak sa prestat hrat na programatora a rob nieco uzitocnejsie.
na nic si nehraju, už jsem psal, že to mám do školy, programování máme poslední rok tak chci projít do dalšího ročníku...
Tak zacni dole novu vetvu daj tam kompletny opraveny zdrojak tak jak to mas teraz, a napis k tomu ze co presne jak presne momentalne s tym zdrojakom nefunguje jak ma.
ted ti nerozumím
Nemame tvoje aktualne zdrojaky, nevieme co tam mas teraz zle.
tady je celý ten program
pong-rar
A jak sa prejavuje zavada? Mne to exe z Debug funguje spravne. Akurat ti tam uchadzaju palky mimo herne pole (nemas kontrolu dosiahnutia okraja plochy pri pohybe palky)
P.S. a reagovanie na char event je dementne ptz sa musi pri stlaceni klavesy cakat na autorepeeat klavesnice. Normalne sa to riesi uplne inac (drzim si flag ci je klavesa stlacena alebo ne, a podla toho pohybujem palkou pri kazdom refreshi alebo v pravidelnych intervaloch). Ale do skoly toto riesit nemusis, profesorovi to je IMHO jedno.
no přesně tak to je jediný problém co mi tam zbývá
Tak si urob kontrolu pohybu palky, nechapem preco to nenaprogramujes :)
Ako prve len podotknem ze this.Top += -20; je dementne, zdravy clovek napise this.Top -= 20;
A to co chces je pridat tam po tom riadku "this.Top += neco;" test if ci je to Top vacsie alebo mesnie ako prislusny okraj plochy (na spodku testujes plus velkost palice) a ak ano nastavit ten this.Top na maximum resp. minimum co dovoluje velkost plochy.
T.j. po znizovani to porovnavas s nulou a po zvysovani s panel1.Height
Mas to v programe 2x, co je tiez dementne (ptz zmysel triedy je mat class v programe len raz, a pouzit 2x steny class pre rozne objekty), ale to uz fakt nemam chut ti vysvetlovat. Co vas v tej skole vobec ucia?
... a predpokladam ze ti to bude hlasit compiler error ptz z classu hrac nevidis panel1, tak si do class hrac pridaj premennu vyska_pola, a inicializuj ju v tom if (e.KeyCode == Keys.F1) na hodnotu panel1.Height
no zkusil jsem něco napsat ale nefunguje mi to zatím to vypadá takto
private void vyjizdeni_palek()
{
if (this.Top > panel1.Height)
{
this.Top += 380;
}
jen nevím kam to přesně napsat já bych to napsal do té třídy ale ta třída nezná panel a když to napíšu do form1 tak jak to bude jaký Top to má měnit
To co si tu vypotil je uplny nezmysel. Evidentne nemas ani paru co znamenaju tie pismena v tom programe. Uz som ti to napisal vyssie, ale u mna si z programovania prepadol (a ten program si garantovane nepisal ty)
imo takhle to také funguje
public void dolu()
{
this.Top += 20;
if (this.Top + this.Height > 380)
this.Top = 380 - this.Height;
jen je jeden problém když se změní velikost panelu tak to fungovat nebude ale já ho měnit nebudu takže by to měla fungovat
Preco si do toho classu nepridas jednu posratu premennu? Je to jeden riadok, a druhy riadok na jej nastavenie v hlavnom classe. Uz som to pisal.
moc děkuju všem za pomoc :)
pomoc by to bola keby si to fakt pochopil a naucil sa z toho nieco. V prvom rade si to v hlave predstavit tie objekty ako nejake bubliny v ktorych su ulozene nejake premenne definovane v classe, funkcie classu pracuju s tymi premennymi objektu. Mozes si tam pridat nejaku dalsiu premennu do classu hrac1 a hrac2, moze sa to robit vsetko aj uplne inac napr. ze kolizie palky o plochu sa mozu kontrolovat aj v tom classe panel1 (tam predsa mas hrac1 a hrac2 pristupne, apod.). "this" vo vnutri classu je samotny objekt, zvonku je to v tvojom pripade "hrac1" alebo "hrac2".
Ne, ty jsi psal, že je ti to jedno a pak už ses neozval.
Dokážeš mi teda správně odpovědět na tyhle otázky?
No vidím, že se neobtěžuješ odpovědět, takže o řešení nejspíš nestojíš. Tak sbohem.
promin vůbec jsem si nevšiml, že je tu druhá strana... jelikož jsem asi furt odpovídal a psal na té straně 1.