미로 류관희
미로만들고이동하는프로그래밍기법 플레이어가직접미로만들어저장 벽의충돌검사 미로프로그램 캔버스 ( 객체, 미로의벽 ) 토큰 ( 오각형 ) 과벽의충돌검사 미로의벽그리기 마우스이용 토큰의이동 ( 화살표를이용 ) 2
1 차버전미로 모든기능을하나의파일 2 차버전미로 미로제작하는코드파일 플레이어가라디오버튼으로미로를선택할수있는코드파일 3
미로구조제작 화살표키로토큰움직이기 충돌검사 인코딩 저장 사용자컴퓨터에서데이터불러오기 4
미로게임의시작화면
미로게임미로벽
미로게임실행과정
플레이어가난이도조절하여 게임
사전준비사항 미로프로그램구성요소 다양한미로벽제공 토큰의이동 ( 화살표키이용 ) 토큰과벽의충돌검사 미로벽정보 인코딩하여저장 벽 ( 시작점과끝점 ) 로컬저장소 (localstorage) 미로의선택 ( 라디오버튼 )
HTML5, CSS, 자바스크립트기능 HTML5 구조 HTML 구조 사용자정의객체를비롯한사용자정의함수 마우스를사용하여 CANVAS 요소에벽을나타내는선분을생성하는패스그리기 토큰의이동을화살표키로사용하기 사용자가만든미로벽을국부저장소에저장하기 사용자객체 배열
벽표시하기 var everything = []; var curwall; var wallwidth = 5; var wallstyle = "rgb(200,0,200)"; var walls = []; function Wall(sx,sy,fx,fy,width,stylestring) { this.sx = sx; this.sy = sy; this.fx = fx; this.fy = fy; this.width = width; this.draw = drawaline; this.strokestyle = stylestring; function drawaline() { ctx.linewidth = this.width; ctx.strokestyle = this.strokestyle; ctx.beginpath(); ctx.moveto(this.sx,this.sy); ctx.lineto(this.fx,this.fy); ctx.stroke();
벽그리기 마우스이용 ( 왼쪽버튼을클릭하면시작하고이동하면선분을그리고버튼을놓으면끝나기 ) function init(){ ctx = document.getelementbyid('canvas').getcontext('2d'); canvas1 = document.getelementbyid('canvas'); canvas1.addeventlistener('mousedown',startwall,false); canvas1.addeventlistener('mousemove',stretchwall,false); canvas1.addeventlistener('mouseup',finish,false); drawall();
벽그리기 function startwall(ev) { var mx; var my; if ( ev.layerx ev.layerx == 0) { mx= ev.layerx; my = ev.layery; else if (ev.offsetx ev.offsetx == 0) { mx = ev.offsetx; my = ev.offsety; curwall = new Wall(mx,my,mx+1,my+1,wallwidth,wallstyle); inmotion = true; everything.push(curwall); drawall();
벽그리기 function stretchwall(ev) { if (inmotion) { var mx; var my; if ( ev.layerx ev.layerx == 0) { // 파이어폭스 mx= ev.layerx; my = ev.layery; else if (ev.offsetx ev.offsetx == 0) { // 오페라 mx = ev.offsetx; my = ev.offsety; curwall.fx = mx; curwall.fy = my; drawall();
벽그리기 function finish(ev) { inmotion = false; walls.push(curwall); function drawall() { ctx.clearrect(0,0,cwidth,cheight); var i; for (i=0;i<everything.length;i++) { everything[i].draw();
그린벽을국부저장소에 저장하기 서버에그린벽을저장하는방식 국부저장소에그린벽을저장하는방식 국부컴퓨터에작은쿠키파일에사용자나웹사이트관리자의편의를위해 ID 혹은암호등의정보를유지 HTML5 localstorage( 브라우저별로국한 )
국부저장소에날짜저장하기 날짜와시간정보저장 Date 함수로날짜 / 시간정보저장 국부저장소 : 문자열이저장되는특정한이름의데이터베이스 ( 키 : 이름, 값 : 문자열, 시스템 : 키와값의쌍 ) 날짜저장프로그램시작화면
<body> <button onclick="javascript:store();"> 날짜정보저장 </button> <button onclick="javascript:fetch();"> 날짜정보불러오기 </button> <button onclick="javascript:remove();"> 날짜정보삭제 </button> </body>
function store() { if (typeof(localstorage) == "undefined") { alert(" 브라우저가 HTML 로컬저장소를인식하지못합니다."); else { try { olddate = new Date(); localstorage.setitem("lastdate",olddate); alert(" 저장됨 : "+olddate); Catch(e) { alert(" 로컬저장소사용오류 : "+e); Return false;
function fetch() { if (typeof(localstorage) == "undefined") { alert(" 브라우저가 HTML 로컬저장소를인식하지못합니다."); else { alert(" 저장됨 "+localstorage.getitem('lastdate')); return false; function remove() { if (typeof(localstorage) == "undefined") { alert(" 브라우저가 HTML 로컬저장소를인식하지못합니다."); else { localstorage.removeitem('lastdate'); alert(" 저장된날짜가삭제되었습니다."); return false;
국부저장소에데이터저장하기 function savewalls() { // 단순히처음과끝쌍을저장 // 긴문자열로변환해야함 var w = []; var allw=[]; var sw; var onewall; var i; var lsname = document.sf.slname.value; for (i=0;i<walls.length;i++) { w.push(walls[i].sx); w.push(walls[i].sy); w.push(walls[i].fx); w.push(walls[i].fy); onewall = w.join("+"); allw.push(onewall); w = []; sw = allw.join(";"); //alert(sw+" 를저장하시겠습니까?"); try { localstorage.setitem(lsname,sw); alert(" 벽이 "+lsname+" 이라는이름으로저장되었습니다."); catch (e) { alert(" 데이터가저장되지않았습니다. 오류 : "+e); return false;
국부저장소에서데이터 function getwalls() { var swalls; var sw; var i; var sx; var sy; var fx; var fy; var curwall; var lsname = document.gf.glname.value; swalls=localstorage.getitem(lsname); if (swalls!=null) { wallstgs = swalls.split(";"); 불러오기 for (i=0;i<wallstgs.length;i++) { sw = wallstgs[i].split("+"); sx = Number(sw[0]); sy = Number(sw[1]); fx = Number(sw[2]); fy = Number(sw[3]); curwall = new Wall(sx,sy,fx,fy,wallwidth,wallstyle); walls.push(curwall); everything.push(curwall); drawall(); else { alert(" 데이터를불러오지못했습니다."); window.addeventlistener('keydown',getkey AndMove,false); return false;
토큰만들기 토큰 : 오각형 (n=5) function Token(sx,sy,rad,stylestring,n) { this.sx = sx; this.sy = sy; this.rad = rad; this.draw = drawtoken; this.n = n; this.angle = (2*Math.PI)/n // 괄호는생략가능 this.moveit = movetoken; this.fillstyle = stylestring;
토큰그리기 function drawtoken() { ctx.fillstyle=this.fillstyle; ctx.beginpath(); var i; var rad = this.rad; ctx.beginpath(); ctx.moveto(this.sx+rad*math.cos(-.5*this.angle),this.sy+ rad*math.sin(-.5*this.angle)); for (i=1;i<this.n;i++) { ctx.lineto(this.sx+rad*math.cos((i-.5)*this.angle), this.sy+rad*math.sin((i-.5)*this.angle)); ctx.fill();
토큰움직이기 화살표를사용하여움직임 화살표키감지하기 var mypent = new Token(100,100,20,"rgb(0,0,250)",5); everything.push(mypent); function init(){ ctx = document.getelementbyid('canvas').getcontext('2d'); canvas1 = document.getelementbyid('canvas'); canvas1.addeventlistener('mousedown',startwall,false); canvas1.addeventlistener('mousemove',stretchwall,false); canvas1.addeventlistener('mouseup',finish,false); window.addeventlistener('keydown',getkeyandmove,false); drawall();
화살표키로토큰움직이기 var mypent = new Token(100,100,20,"rgb(0,0,250)",5); everything.push(mypent); function getkeyandmove(event) { var keycode; if(event == null) { keycode = window.event.keycode; window.event.preventdefault(); else { keycode = event.keycode; event.preventdefault();
switch(keycode) { case 37: // 왼쪽화살표 mypent.moveit(-unit,0); break; case 38: // 위쪽화살표 mypent.moveit(0,-unit); break; case 39: // 오른쪽화살표 mypent.moveit(unit,0); break; case 40: // 아래쪽화살표 mypent.moveit(0,unit); break; default: window.removeeventlistener('keydown',getkeyandmove,false); drawall();
function movetoken(dx,dy) { this.sx +=dx; this.sy +=dy; var i; var wall; for(i=0;i<walls.length;i++) { wall = walls[i]; if (intersect(wall.sx,wall.sy,wall.fx,wall.fy,this.sx,this.sy,this.rad)) { this.sx -=dx; this.sy -=dy; break;
토큰과벽의충돌감지 Intersect 함수 주어진중심과반경의원이선분과만나는지검사 만나면 TRUE, 그렇지않으면 FALSE 직선 : (sx, sy), (fx, fy) 직선의방정식 : x = sx+t*(fx-sx), y=sy+t*(fy-sy) 원 : 중심 (cx,cy), 반지름 rad
function intersect(sx,sy,fx,fy,cx,cy,rad) { var dx; var dy; var t; var rt; // t 가 0.0 에서 1.0 으로갈때선분을매개변수로나타낸후 // 각점부터 cx,cy 까지의거리제곱을작성하고 // 미분해서결과가 0 이되는 t 값을계산하여최솟값을구함 dx = fx-sx; dy = fy-sy; t =0.0-((sx-cx)*dx+(sy-cy)*dy)/((dx*dx)+(dy*dy)); if (t<0.0) { t=0.0; else if (t>1.0) { t = 1.0; // 이 t 에서의거리가반경보다작으면, 제곱을비교 dx = (sx+t*(fx-sx))-cx; dy = (sy +t*(fy-sy))-cy; rt = (dx*dx) +(dy*dy); if (rt<(rad*rad)) { return true; else { return false;
2 차버젼
난이도선택 <body onload="init();" > <canvas id="canvas" width="900" height="350"> 이브라우저는 HTML5 의 canvas 요소를지원하지않습니다. </canvas> <br/> 미로를불러오려면수준을선택하고 ' 미로불러오기 ' 버튼을클릭하세요. <form name="gf" onsubmit="return getwalls()" > <br/> <input type="radio" value="hard" name="level" /> 어려움 <br/> <input type="radio" value="moderate" name="level" /> 보통 <br/> <input type="radio" value="easy" name="level" /> 쉬움 <br/> <input type="submit" value=" 미로불러오기 "/><br/> </form> <p> 토큰을이동하려면화살표키를누르세요. </p> </body>
선택한미로벽불러오기 function getwalls() { var swalls; var sw; var i; var sx; var sy; var fx; var fy; var curwall; var lsname; for (i=0;i<document.gf.level.length;i++) { if (document.gf.level[i].checked) { lsname= document.gf.level[i].value+"maze"; break;
//alert(" 로컬저장소이름 : "+lsname); swalls=localstorage.getitem(lsname); if (swalls!=null) { wallstgs = swalls.split(";"); walls = []; // walls 배열에서벽제거 everything = []; everything.push(mypent); for (i=0;i<wallstgs.length;i++) { sw = wallstgs[i].split("+"); sx = Number(sw[0]); sy = Number(sw[1]); fx = Number(sw[2]); fy = Number(sw[3]); curwall = new Wall(sx,sy,fx,fy,wallwidth,wallstyle); walls.push(curwall); everything.push(curwall); drawall(); else { alert(" 데이터를불러오지못했습니다."); window.addeventlistener('keydown',getkeyandmove,false); return false;