1. Введение на фон игры (ерунда, написанная спереди):
Однажды в начале мая я увидел определенный веб -сайт, рекомендующий эту игру, Pongo. Я выглядел довольно хорошо и попробовал это с iPad. Играя в две игры, я почувствовал, что это была хорошая вещь, и это было довольно приятно, потому что это была игра, которая была типом причитающейся руки. Все это знают.
Но через некоторое время я обнаружил, что в игре, казалось, были некоторые ошибки на iPad. Я бы застрял после игры на некоторое время, и я мог только заставить его отступить. Это было действительно душераздирающе, и запись все еще ждала, чтобы быть сломанной.
что делать? Идея о том, что лучше играть в игры, чем играть в свои собственные игры, снова оказалась жестокой, а затем я бросил подушку в душераздирающий друг моего друга. Я молча вернулся на компьютер и начал писать что -то, что не мог застрять.
Потребовалось около двух часов, чтобы записать основные рамки, а затем бросил ее в SinaApp и попробовал. Это было в основном лучше всего играть, а затем принять душ и ложиться спать.
Когда я проснулся на следующий день, я провел некоторое время на разработку интерфейса, потому что мне нечего было делать на выходных. К сожалению, я сам нашел несколько серьезных ошибок, и, наконец, потребовалось некоторое время, чтобы исправить их.
Наконец, игра была названа «Pongo+» (нажмите на меня, чтобы играть на мобильных телефонах). Компьютер на данный момент не поддерживается. Кстати, исходный код был загружен на GitHub, а модуль оценки отправки был удален.
2. Веб -сайт игровой пробной версии:
Pongo+ (только мобильный): http://mypongo.sinaapp.com/
GitHub Open Source (Fork может сделать игру лучше): https://github.com/chenreason/pongo/blob/gh-pages/index.html
3. Правила игры и игровой процесс:
Нажатие на экран изменит направление движения рамки. Нажатие на рамку разведет направление рамки один раз, с целью просто блокировать маленькие шарики, катящиеся вокруг и не допустить того, чтобы они не выбежали из большого круга. Чем дольше время, тем лучше! Наконец, вы можете отправить свои собственные результаты для рейтинга!
4. Технология, используемая в игре:
HTML, CSS, JavaScript, Canvas, PHP
5. Идеи дизайна игры:
а) Используйте холст, чтобы нарисовать основной интерфейс игры. Дно представляет собой монохромный прямоугольник, покрытый большим кругом, а на большом круге нарисованы небольшой круг и перегородку. Существует также супер маленький круг с размером 1PX в середине перегородки (для обнаружения столкновений).
б) Существует 8 направлений движения небольших кружков: верхний, нижний, слева, справа, в верхнем левом, нижнем левом, верхнем и нижнем правом правом.
c) Есть только два направления движения перегородки, по часовой стрелке и против часовой стрелки.
D) Обнаружение столкновений не включает использование двигателя, а скорее делает расстояние на расстоянии на основе небольшого круга и супер круга в середине перегородки, тем самым достигая простого обнаружения столкновений.
e) направление отскока после определения мяча, и общие знания используются для его перечисления, и в общей сложности существует 8 ситуаций.
6. Трудности в реализации игры:
а) Обнаружение столкновения.
б) Таймер SetInterval сроки очистки и ясный и тщательный.
в) взаимосвязь между продолжительностью цикла таймера и игровым опытом.
D) Проблемы беглости игры, вызванные различной производительностью устройств Android и iOS.
7. Существующие проблемы с игрой:
а) Поскольку обнаружение столкновений заключается в сравнении центрального расстояния между двумя кругами и включает использование таймеров из -за чрезвычайно короткого интервала таймера, десятки столкновений фактически произошли за столкновением, наблюдаемым невооруженным глазом. Это приведет к тому, что фактическое направление отскока мяча отличается от фактической физической теоремы. После оптимизации вероятность возникновения низкая, но ее не избежали. Следовательно, некоторые игроки обнаружили, что если круг не попадет в центр перегородки точно, это может привести к выходу из строя.
б) Поскольку функции слишком многословные, низкоэффективность и использование таймеров, игровой опыт на Android отличается от iOS или других мобильных устройств (в целом, iOS связан с Android).
c) Список рейтинга не достиг автоматических обновлений в реальном времени. (База данных еще не будет использоваться)
8. Предварительный просмотр интерфейса игры:
(Рисунок 1 - это первое издание, рисунок 2 удалил кнопку, рисунок 3 - последнее издание, а рисунок 4 - список ранжирования)
Рисунок 1
Рисунок 2
Рисунок 3
9. Часть исходного кода игры JavaScript:
Кода -копия выглядит следующим образом:
var ifingame = 0;
var maxgrade = 0, grade = 0;
var Grade1, класс2;
VAR ICEMAME;
var gamesspeed = 1,4; // Скорость мяча
var linespeed = math.pi/95; // Скорость трека
var crashdistancefaild = -7; // Параметры обнаружения столкновений
var crashdistancesucc = 15
var fantanjuli = 7;
var themaxgradeline = 12,1;
Функция getCookie1 (прозвище)
{
if (document.cookie.length> 0)
{
c_start = document.cookie.indexof (никнам + "=")
if (c_start! =-1)
{
C_START = C_START + NICKNAME.Length + 1;
c_end = document.cookie.indexof (",", c_start);
if (c_end ==-1)
c_end = document.cookie.length;
return unescape (document.cookie.substring (c_start, c_end));
}
}
возвращаться ""
}
Функция getCookie2 (MyMaxGrade)
{
if (document.cookie.length> 0)
{
c_start = document.cookie.indexof (mymaxgrade + "=")
if (c_start! =-1)
{
c_start = c_start + mymaxgrade.length + 1;
c_end = document.cookie.indexof (";", c_start);
if (c_end ==-1)
c_end = document.cookie.length;
return unescape (document.cookie.substring (c_start, c_end));
}
}
возвращаться ""
}
Функция SetCookie (прозвище, значение, MyMaxGrade, MaxGrade, истечь)
{
var exdate = new Date ()
exdate.setDate (exdate.getDate ()+истечь)
document.cookie = никнам + "=" + escape (value) + "," + mymaxgrade + "=" + escape (maxgrade) + ((срок действия == null)? "": "; истекает =" + exdate.togmtString ());
}
функция checkcookie ()
{
nichname = getCookie1 ('псевдоним');
maxgrade = parseint (getcookie2 ('mymaxgrade'));
if (isnan (maxgrade) == true)
{
maxgrade = 0;
}
if (псевдоним! = NULL && Lickname! = "")
{
ALERT («Добро пожаловать»+никнам+'Back!'+'/n'+"Если вам это нравится, пожалуйста, поделитесь этим ~");
}
еще
{
nickname = reffice ('Пожалуйста, введите свой прозвище: (имя слишком длинное и будет отображаться неполным)', "")
if (псевдоним! = NULL && Lickname! = "")
{
var maxgradestring = maxgrade.toString ();
SetCookie («Прозвище», прозвище, «MyMaxGrade», MaxGradestring, 365);
}
}
}
var objpane = document.getElementById ("панель");
var ctxpane = objpane.getContext ("2d");
ctxpane.translate (150 150); // Требуется перевод центральной точки Canvas
Функция sendmail ()
{
if (Grade2> Themaxgureline)
var max_grade = Grade2;
window.location.href = 'index.php? max_grade ='+max_grade+'& nick_name ='+lickname;
/* {
<? Php
$ grade = $ _ get ['max_grade'];
$ lickname = $ _ get ['nick_name'];
$ mail = new saemail ();
$ ret = $ mail-> Quicksend ('[email protected]', $ grade, $ chicname, '[email protected]', 'mypongo');
$ mail-> clean ();
?>
}*/
оповещение (прозвище+«Ваша оценка:»+Grade2+«Успешно отправлено ~»);
}
var gamederation = {
Шан: 1,
Ся: 5,
Zuo: 7,
Вы: 3,
Zuoshang: 8,
Zuoxia: 6,
Youshang: 2,
Youxia: 4,
Часы: 0,
Антикол: 9,
};//направление
var canvas = {
Ширина: 300,
высота: 300,
};//холст
var BigCircle = {// Параметр Big Circle
x: 0, // Значение координаты оси X в центре круга
y: 0, // Значение координаты оси Y в центре круга
R: 150, // радиус круга
C: 'RGB (255,255,255)',
}; // dayuan
var smallcircle = {// smallcircle parameter
x: 0, // Значение координаты оси X в центре круга
y: 0, // Значение координаты оси Y в центре круга
R: 12, // радиус круга
C: 'RGB (204,105,106)',
Направление: GamedIere.xia,
}; // маленький круг
var line = {// параметры линии перегородки
x: 0, // Значение координаты оси X в центре круга
y: 0, // Значение координаты оси Y в центре круга
R: 150, // радиус дуги
начало: (math.pi/2-math.pi/16),
конец: (math.pi/2+math.pi/16),
C: 'RGB (55,55,55)',
Направление: GamedIeration.Anticlock,
}; // Линия отслеживания
var dot = {// Параметры точки отслеживания
X: (bigCircle.r*math.cos (line.start+math.pi/16)), // используйте большой круг в качестве источника
y: (bigcircle.r*math.sin (line.start+math.pi/16)),
R: 1,
} // Точка отслеживания
Функция changelinedRection ()
{
if (line.dieration == gamedirection.clock)
{
Line.Direction = GamedIere.Anticlock;
}
еще
{
Line.Direction = GamedIere.Clock;
}
}
функция getDistance () {
var distance = math.sqrt ((smallcircle.x)*(smallcircle.x)+(smallcircle.y)*(smallcircle.y));
ДАВАТЬ ДАЛИ;
} // Вернуться на квадратное расстояние между маленьким мячом и большим центром круговых центров ()
Функция ifgameover () {// судить, находится ли она вне границ
if ((getDistance () - bigCircle.r)> 5)
вернуть истину;
еще
вернуть ложь;
} // Судите, заканчивается ли игра ifgameover ()
Функция ifcrash () {// обнаружение столкновений
var dx = dot.x-smallcircle.x;
var dy = dot.y-smallcircle.y;
var dd = math.sqrt (dx*dx+dy*dy);
if (dd <crashdistancesucc)
вернуть истину;
еще
вернуть ложь;
} // Обнаружение столкновения ifcrash ()
Функция randomback ()
{
var x = math.floor (math.random ()*3);
Switch (SmallCircle.Direction) {
Case GamedIere.shang:
{
переключатель (x)
{
Случай 0:
SmallCircle.Direction = GamedIerection.xia;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIere.zuoxia;
smallcircle.x = smallcircle.x-fantanjuli;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIere.youxia;
smallcircle.x = smallcircle.x+fantanjuli;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
по умолчанию:
перерыв;
}перерыв;
}
Case GamedIere.xia:
{
переключатель (x)
{
Случай 0:
SmallCircle.Direction = GamedIere.shang;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIere.zuoshang;
smallcircle.x = smallcircle.x-fantanjuli;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIere.youshang;
smallcircle.x = smallcircle.x+fantanjuli;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
по умолчанию:
перерыв;
}перерыв;
}
Case GamedIere.zuo:
{
переключатель (x)
{
Случай 0:
SmallCircle.Direction = GamedIer. You;
smallcircle.x = smallcircle.x+fantanjuli;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIere.youshang;
smallcircle.x = smallcircle.x+fantanjuli;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIere.youxia;
smallcircle.x = smallcircle.x+fantanjuli;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
по умолчанию:
перерыв;
}перерыв;
}
Case GamedIeration.ou:
{
переключатель (x)
{
Случай 0:
SmallCircle.Direction = GamedIere.zuo;
smallcircle.x = smallcircle.x-fantanjuli;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIere.zuoxia;
smallcircle.x = smallcircle.x-fantanjuli;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIere.zuoshang;
smallcircle.x = smallcircle.x-fantanjuli;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
по умолчанию:
перерыв;
}перерыв;
}
Case GamedIere.zuoshang:
{
переключатель (x)
{
Случай 0:
SmallCircle.Direction = GamedIere.youxia;
smallcircle.x = smallcircle.x+fantanjuli;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIerection.xia;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIer. You;
smallcircle.x = smallcircle.x+fantanjuli;
перерыв;
по умолчанию:
перерыв;
}перерыв;
}
Case GamedIere.zuoxia:
{
переключатель (x)
{
Случай 0:
SmallCircle.Direction = GamedIere.youshang;
smallcircle.x = smallcircle.x+fantanjuli;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIere.shang;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIer. You;
smallcircle.x = smallcircle.x+fantanjuli;
перерыв;
по умолчанию:
перерыв;
}перерыв;
}
Case GamedIere.youshang:
{
переключатель (x)
{
Случай 0:
SmallCircle.Direction = GamedIere.zuoxia;
smallcircle.x = smallcircle.x-fantanjuli;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIere.zuo;
smallcircle.x = smallcircle.x-fantanjuli;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIerection.xia;
smallcircle.y = smallcircle.y+fantanjuli;
перерыв;
по умолчанию:
перерыв;
}перерыв;
}
Case GamedIere.youxia:
{
переключатель (x)
{
Случай 0:
SmallCircle.Direction = GamedIere.zuoshang;
smallcircle.x = smallcircle.x-fantanjuli;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIere.zuo;
smallcircle.x = smallcircle.x-fantanjuli;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIere.shang;
smallcircle.y = smallcircle.y-fantanjuli;
перерыв;
по умолчанию:
перерыв;
}перерыв;
}
по умолчанию:
{
перерыв;
}
}
} // мяч случайным образом изменил randomback ()
Функция SmallcircReection ()
{
Switch (SmallCircle.Direction) {// Перемещение в соответствии с направлением мяча
Case GamedIere.shang:
{
smallcircle.y = smallcircle.y-gamespeed;
Grade ++;
if (Grade> Maxgrade)
{
maxgrade = grade;
newRecoder ();
}
addone ();
перерыв;
}
Case GamedIere.xia:
{
SmallCircle.Y = SmallCircle.Y+GameSpeed;
Grade ++;
if (Grade> Maxgrade)
{
maxgrade = grade;
newRecoder ();
}
addone ();
перерыв;
}
Case GamedIere.zuo:
{
smallcircle.x = smallcircle.x-gamespeed;
Grade ++;
if (Grade> Maxgrade)
{
maxgrade = grade;
newRecoder ();
}
addone ();
перерыв;
}
Case GamedIeration.ou:
{
smallcircle.x = smallcircle.x+gamesspeed;
Grade ++;
if (Grade> Maxgrade)
{
maxgrade = grade;
newRecoder ();
}
addone ();
перерыв;
}
Case GamedIere.zuoshang:
{
SmallCircle.x = SmallCircle.x-Gamespeed*0,8;
smallcircle.y = smallcircle.y-gamespeed*0,8;
Grade ++;
if (Grade> Maxgrade)
{
maxgrade = grade;
newRecoder ();
}
addone ();
перерыв;
}
Case GamedIere.zuoxia:
{
SmallCircle.x = SmallCircle.x-Gamespeed*0,8;
smallcircle.y = smallcircle.y+gamespeed*0,8;
Grade ++;
if (Grade> Maxgrade)
{
maxgrade = grade;
newRecoder ();
}
addone ();
перерыв;
}
Case GamedIere.youshang:
{
smallcircle.x = smallcircle.x+gamespeed*0,8;
smallcircle.y = smallcircle.y-gamespeed*0,8;
Grade ++;
if (Grade> Maxgrade)
{
maxgrade = grade;
newRecoder ();
}
addone ();
перерыв;
}
Case GamedIere.youxia:
{
smallcircle.x = smallcircle.x+gamespeed*0,8;
smallcircle.y = smallcircle.y+gamespeed*0,8;
Grade ++;
if (Grade> Maxgrade)
{
maxgrade = grade;
newRecoder ();
}
addone ();
перерыв;
}
по умолчанию:
{
перерыв;
}
}
} // Шар перемещает Smallcircredection ()
/*Нарисуйте нижний круг*/
ctxpane.beginpath (); // dayuan
ctxpane.arc (bigcircle.x, bigcircle.y, bigcircle.r, 0, math.pi*2, true);
ctxpane.fillstyle = bigcircle.c;
ctxpane.fill ();
ctxpane.closepath ();
/*Нарисуйте линию нижнего отслеживания*/
ctxpane.beginpath ();
ctxpane.linewidth = 6;
ctxpane.strokestyle = line.c;
ctxpane.arc (line.x, line.y, line.r, line.start, line.end, false);
ctxpane.stroke ();
ctxpane.closepath ();
Функция tapme () // tapme
{
ctxpane.beginpath ();
ctxpane.strokestyle = "rgb (255 222,195)";
ctxpane.font = "80px papyrus";
ctxpane.stroketext ('tap',-95,30);
ctxpane.fillstyle = "rgb (255,205,105)";
ctxpane.font = "35px papyrus";
ctxpane.filltext ('me', 70,30);
ctxpane.closepath ();
}
Функция newRecoder ()
{
ctxpane.beginpath ();
ctxpane.fillstyle = "rgb (255,0,0)";
ctxpane.font = "18px papyrus";
ctxpane.filltext ("new!", 58,80);
ctxpane.closepath ();
}
Функция addone ()
{
Grade1 = (класс/150) .tofixed (1);
Grade2 = (maxgrade/150) .tofixed (1);
var way1 = "сейчас";
var specile2 = "Лучший"
ctxpane.beginpath ();
ctxpane.strokestyle = "rgb (250 222,185)";
ctxpane.font = "60px papyrus";
ctxpane.stroketext (Grade1, -45, -60);
ctxpane.stroketext (класс 2, -45,100);
ctxpane.fillstyle = "rgb (255,0,100)";
ctxpane.font = "15px papyrus";
ctxpane.filltext (say1,58, -60);
ctxpane.fillstyle = "rgb (255,0,100)";
ctxpane.font = "15px papyrus";
ctxpane.filltext (say2,58,100);
ctxpane.closepath ();
}
функция movetest () {
if (ifgameover ())
{
ifingame = 0;
if (maxgrade> parseint (getcookie2 ('mymaxgrade')))))))))))))
{
SetCookie («Прозвище», прозвище, «mymaxgrade», maxgrade.tostring (), 365);
}
ClearInterval (таймер);
tapme ();
}
еще
{
if (ifcrash ())
{
randomback ();
}
ctxpane.clearrect (-150, -150 300 300); // очистить экран
ctxpane.beginpath (); // dayuan
ctxpane.arc (bigcircle.x, bigcircle.y, bigcircle.r, 0, math.pi*2, true);
ctxpane.fillstyle = bigcircle.c;
ctxpane.fill ();
ctxpane.closepath ();
if (line.direction == gamedirection.clock) // Линия отслеживания по часовой стрелке
{
line.start = line.start + linepeed;
line.end = line.end +linepeed;
ctxpane.beginpath ();
ctxpane.linewidth = 4;
ctxpane.strokestyle = line.c;
ctxpane.arc (line.x, line.y, line.r, line.start, line.end, false);
ctxpane.stroke ();
ctxpane.closepath ();
}
if (line.direction == gamedirection.anticlock) // отслеживание против часовой стрелки
{
line.start = line.start - linepeed;
line.end = line.end -linespeed;
ctxpane.beginpath ();
ctxpane.linewidth = 4;
ctxpane.strokestyle = line.c;
ctxpane.arc (line.x, line.y, line.r, line.start, line.end, false);
ctxpane.stroke ();
ctxpane.closepath ();
}
dot.x = bigcircle.r*math.cos (line.start+math.pi/32) // Точка отслеживания
dot.y = bigcircle.r*math.sin (line.start+math.pi/32)
ctxpane.beginpath (); // Онлайн -точка отслеживания
ctxpane.arc (dot.x, dot.y, dot.r, 0, math.pi*2, true);
ctxpane.fillstyle = smallcircle.c;
ctxpane.fill ();
ctxpane.closepath ();
Smallcircredirection (); // smallcircredirection (); //
ctxpane.save ();
ctxpane.beginpath ();
ctxpane.arc (smallcircle.x, smallcircle.y, smallcircle.r, 0, math.pi*2, true);
ctxpane.fillstyle = smallcircle.c;
ctxpane.fill ();
ctxpane.closepath ();
ctxpane.restore ();
}
} // Основная функция
///////////////////////////////////////////
tapme ();
var таймер;
function startGame () {// запустить игру
if (ifingame == 0)
{
ifingame = 1;
Grade = 0;
var xx = math.floor (math.random ()*8);
/* Переключатель (xx)
{
Случай 0:
SmallCircle.Direction = GamedIere.shang;
перерыв;
Случай 1:
SmallCircle.Direction = GamedIerection.xia;
перерыв;
Случай 2:
SmallCircle.Direction = GamedIere.zuo;
перерыв;
Случай 3:
SmallCircle.Direction = GamedIer. You;
перерыв;
Случай 4:
SmallCircle.Direction = GamedIere.zuoshang;
перерыв;
Случай 5:
SmallCircle.Direction = GamedIere.zuoxia;
перерыв;
Случай 6:
SmallCircle.Direction = GamedIere.youshang;
перерыв;
Случай 7:
SmallCircle.Direction = GamedIere.youxia;
перерыв;
по умолчанию:
перерыв;
}*/
SmallCircle.Direction = GamedIerection.xia;
smallcircle.x = smallcircle.y = 0;
line.start = math.pi/2-math.pi/26;
line.end = math.pi/2+math.pi/26;
Line.Direction = GamedIere.Anticlock;
ClearInterval (таймер);
timer = setInterval (movtest, 10);
}
} // запустить Game Startgame ()
Функция opentop ()
{
window.location = "http://pongotop.sinaapp.com";
}
10. Написано в конце
Это чисто самооценка. На третий день после написания я был занят отправкой резюме, чтобы найти стажировку, и у меня не было времени позаботиться об этом. Я бросил его в свой круг друзей, чтобы мои друзья могли играть. Этот месяц прошел, и я снова смотрю эту игру. Я чувствую, что он не должен был погибнуть так. У меня нет никаких навыков, и я делаю это очень хорошо. Поэтому я надеюсь, что эта статья может помочь некоторым друзьям, которые заинтересованы в Понго. Кроме того, я надеюсь, что если какой -либо эксперт в этой области даст мне советы, если он увидит это, он приветствует меня, чтобы оставить сообщение для всех сомнений и советов. Спасибо!