diff --git a/src/game/main_menu/animal_record_list.js b/src/game/main_menu/animal_record_list.js new file mode 100644 index 0000000..0911955 --- /dev/null +++ b/src/game/main_menu/animal_record_list.js @@ -0,0 +1,105 @@ +function AnimalRecordList() { + this.animals = []; + this.activeAnimalIndex = -1; + + var animalCount = Animal.SPECIES_DATA.length; + var lineWidth = GAME_SCREEN_SIZE.x - AnimalRecordList.MARGIN_X * 2; + // console.log("lineWidth : " + lineWidth); + var offsetAnimal = lineWidth / (animalCount - 1); + // console.log("animalCount : " + animalCount); + // console.log("offsetAnimal : " + offsetAnimal); + + this.activeAnimalIndex = 0; + + game.add.graphics() + .beginFill(AnimalRecordList.COLOR_BG, 1) + .drawRect( + 0, ScreenTopUI.BG_HEIGHT, + game.world.width, 80 + ); + + for(var i = 0; i < animalCount; i++) { + this.animals[i] = new Animal( + Animal.TYPE_ICON, + i, + AnimalRecordList.MARGIN_X + offsetAnimal * i, + AnimalRecordList.ANIMAL_LIST_POS_Y + ); + this.inactivate(i); + } + + // this.activate(this.activeAnimalIndex); + // this.tweenAnimation(Animal.ANIMATION_TYPE_DAMAGE); +} + +AnimalRecordList.prototype.printScore = function(type) { + var animalCount = Animal.SPECIES_DATA.length; + var lineWidth = GAME_SCREEN_SIZE.x - AnimalRecordList.MARGIN_X * 2; + // console.log("lineWidth : " + lineWidth); + var offsetAnimal = lineWidth / (animalCount - 1); + + var titleTextStyle = { font: "16px Arial", fill: "#fff", align: "center"}; + var typingCount = 0; + var animalData = null; + for(var i = 0; i < animalCount; i++) { + animalData = Animal.SPECIES_DATA[i]; + if(type == AnimalRecordList.TYPE_PRACTICE) + typingCount = RecordUtil.getRecordValueWithUnit(animalData.practiceTypingCount, 1); + else + typingCount = RecordUtil.getRecordValueWithUnit(animalData.testTypingCount, 1); + + var recordText = game.add.text( + AnimalRecordList.MARGIN_X + offsetAnimal * i, + AnimalRecordList.ANIMAL_LIST_POS_Y + AnimalRecordList.RECORD_TEXT_OFFSET_Y, + typingCount, titleTextStyle + ); + recordText.anchor.set(0.5); + recordText.addColor(AnimalRecordList.COLOR_SCORE_DEFAULT_TEXT, 0); + recordText.stroke = "#333"; + recordText.strokeThickness = 3; + recordText.setShadow(1, 1, 'rgba(0, 0, 0, 0.5)', 2); + } +} + +AnimalRecordList.prototype.activate = function(index) { + this.inactivate(this.activeAnimalIndex); + + this.activeAnimalIndex = index; + + this.animals[this.activeAnimalIndex].setScale(2); + this.animals[index].setAlpha(1); + this.animate(this.activeAnimalIndex); +} + +AnimalRecordList.prototype.inactivate = function(index) { + this.animals[index].stopAnimation(); + this.animals[index].setScale(1); + this.animals[index].setAlpha(AnimalRecordList.ALPHA_INACTIVE); +} + +AnimalRecordList.prototype.animate = function(index) { + var animalData = Animal.SPECIES_DATA[index]; + this.animals[index].startAnimation(animalData); +} + +AnimalRecordList.prototype.stopAnimation = function() { + this.animals[this.activeAnimalIndex].stopAnimation(); +} + +AnimalRecordList.prototype.tweenAnimation = function(animationType) { + this.animals[this.activeAnimalIndex].tweenAnimation(animationType); +} + + +AnimalRecordList.MARGIN_X = 100; +AnimalRecordList.ANIMAL_LIST_POS_Y = 90; +AnimalRecordList.RECORD_TEXT_OFFSET_Y = 36; + +AnimalRecordList.ALPHA_INACTIVE = 0.3; + +AnimalRecordList.TYPE_PRACTICE = 0; +AnimalRecordList.TYPE_TEST = 1; + +AnimalRecordList.COLOR_BG = 0x77aadd; //0x99ccff; +AnimalRecordList.COLOR_SCORE_DEFAULT_TEXT = "#bbddff"; +AnimalRecordList.COLOR_SCORE_CLEARED_TEXT = "#ffffff"; \ No newline at end of file diff --git a/src/game/main_menu/app_area_bg.js b/src/game/main_menu/app_area_bg.js new file mode 100644 index 0000000..00adbe1 --- /dev/null +++ b/src/game/main_menu/app_area_bg.js @@ -0,0 +1,26 @@ +function AppAreaBG(color, alpha, x, y, width, height) { + game.add.graphics() + .beginFill(color, alpha) + .drawRect(x, y, width, height); +} + +AppAreaBG.prototype.printText = function(text, x, y, size, color, alpha) { + var fontStyle = { font: "36px Arial", fill: "#fff", align: "left", boundsAlignH: "left", boundsAlignV: "bottom" }; + var titleText = game.add.text(x, y, text, fontStyle); + titleText.anchor.set(0.5); + titleText.fontSize = size; + titleText.addColor(color, 0); + titleText.alpha = alpha; +} + +AppAreaBG.COLOR_MOUSE_APP = 0xffce54; +AppAreaBG.COLOR_TYPING_APP = 0x99ccff; + +AppAreaBG.COLOR_TYPING_KOREAN = 0xbbccff; +AppAreaBG.COLOR_TYPING_ENGLISH = 0x88bbff; + +AppAreaBG.GAP_X = 10; +AppAreaBG.GAP_Y = 10; + +AppAreaBG.MARGIN_X = 20; +AppAreaBG.MARGIN_Y = 10; \ No newline at end of file diff --git a/src/game/main_menu/main.js b/src/game/main_menu/main.js new file mode 100644 index 0000000..25091c5 --- /dev/null +++ b/src/game/main_menu/main.js @@ -0,0 +1,12 @@ +///////////////////////////// +// Main game + +var CONTENT_ID = "MainMenu"; + +var game = new Phaser.Game( + GAME_SCREEN_SIZE.x, GAME_SCREEN_SIZE.y, + Phaser.CANVAS, CONTENT_ID +); + +game.state.add('MainMenu', MainMenu); +game.state.start('MainMenu'); diff --git a/src/game/main_menu/main_menu.js b/src/game/main_menu/main_menu.js new file mode 100644 index 0000000..62f92af --- /dev/null +++ b/src/game/main_menu/main_menu.js @@ -0,0 +1,266 @@ +var MainMenu = { + + preload: function() { + game.load.image('icon_fullscreen', '../../../resources/image/icon/fullscreen_white.png'); + }, + + create: function() { + game.stage.backgroundColor = '#4d4d4d'; + + // mouse app area + var mouseBG = new AppAreaBG( + AppAreaBG.COLOR_MOUSE_APP, 1, + 0, 60, + GAME_SCREEN_SIZE.x, 280 + ); + mouseBG.printText( + "마우스 연습 앱", + game.world.centerX, 200, + 170, "#000", 0.03 + ); + + // typing app area + var typingBG = new AppAreaBG( + AppAreaBG.COLOR_TYPING_APP, 1, + 0, 340, + GAME_SCREEN_SIZE.x, 378 + ); + typingBG.printText( + "타 자 연 습 앱", + game.world.centerX, 490, + 170, "#000", 0.03 + ); + + + // keyboard shortcut + this.keyboardShortcut = new KeyboardShortcut(); + this.keyboardShortcut.addCallback( + Phaser.KeyCode.ESC, // keyCode + null, // keyDownHandler + (function() { this.back(); }).bind(this), // keyUpHandler + "menu_app" // callerClassName + ); + + // top ui + // var screenTopUI = new ScreenTopUI(); + // screenTopUI.makeBackButton( (function() { this.back(); }).bind(this) ); + // screenTopUI.makeFullScreenButton(); + // this.loadAllowEditEnterCode(screenTopUI); + + + // bottom ui + var screenBottomUI = new ScreenBottomUI(); + // ScreenBottomUI.printLeftText("게임 진행 정보"); + // var playingAppName = appInfoManager.getAppNameKorean(sessionStorageManager.playingAppName); + // ScreenBottomUI.printCenterText(playingAppName); + screenBottomUI.printCenterText("메뉴"); + screenBottomUI.printRightText(sessionStorageManager.getPlayerName()); + + new WelcomePlayerText(sessionStorageManager.getPlayerName()); + if(isExperiencePlayerAccount()) { + game.time.events.add(Phaser.Timer.SECOND * 2.5, + (function() { new NoticeExperiencePlayerText(); } ), + this + ); + } + + + this.loadAppData(); + }, + + + back: function() { + sessionStorageManager.clear(); + location.href = '../../web/client/login.html'; + }, + + loadAllowEditEnterCode: function(screenTopUI) { + var dbConnectManager = new DBConnectManager(); + dbConnectManager.requestAllowEditEnterCode( + sessionStorageManager.getMaestroID(), + + (function(replyJSON) { + if(replyJSON["AllowEditEnterCode"] == "1") { + screenTopUI.makeSetupButton( (function() { + console.log("setup"); + location.href = '../../web/client/setup.html'; + }).bind(this) ); + } + }).bind(this), + + (function(replyJSON) { + this.loadFailed(replyJSON); + }).bind(this) + ); + }, + + loadAppData: function() { + var dbConnectManager = new DBConnectManager(); + dbConnectManager.requestMenuAppList( + sessionStorageManager.getMaestroID(), + (function(replyJSON) { + this.loadSucceeded(replyJSON); + }).bind(this), + (function(replyJSON) { + this.loadFailed(replyJSON); + }).bind(this) + ); + }, + + loadSucceeded: function(replyJSON) { + // console.log(replyJSON); + + this.makeMouseAppButtons( + replyJSON.MouseAppList, + replyJSON.MouseActiveAppList + ); + this.makeTypingButtons( + replyJSON.TypingPracticeAppCount, + replyJSON.TypingTestAppCount, + replyJSON.TypingAppList, + replyJSON.TypingActiveAppList + ); + }, + + hasApp: function(appID, appList) { + for(var i = 0; i < appList.length; i++) { + if(appList[i].AppID === appID) + return true; + } + + return false; + }, + + makeMouseAppButtons: function(appList, activeAppList) { + // console.log(appList); + + var mouseAppCount = Object.keys(appList).length; + + for(var i = 0; i < mouseAppCount; i++) { + var posX = this.getButtonPosX(i, mouseAppCount); + var posY = this.getButtonPosY(i, mouseAppCount, GameAppButton.BUTTON_UPPER_POS_Y); + + var app = appList[i]; + var gameAppButton = new GameAppButton( + posX, posY, + GameAppButton.TYPE_MOUSE_APP, + RoundRectButton.NONE_ICON, app.KoreanName, + { + AppID: app.AppID, + AppName: app.AppName, + KoreanName: app.KoreanName + } + ); + + if(!this.hasApp(app.AppID, activeAppList)) + gameAppButton.setInputEnabled(false); + } + }, + + makeTypingButtons: function(typingPracticeAppCount, typingTestAppCount, appList, activeAppList) { + // console.log(typingPracticeAppCount); + // console.log(typingTestAppCount); + // console.log(appList); + + var isTypingPracticeAppExist = typingPracticeAppCount > 0 ? true : false; + var isTypingTestAppExist = typingTestAppCount > 0 ? true : false; + + var typingAppTotalCount = Object.keys(appList).length; + var typingAppIndex = 0; + + + // typing tab buttons + var typingPracticeTabButton = new TypingTabButton( + TypingTabButton.PRACTICE_BUTTON_POS_X, TypingTabButton.BUTTON_POS_Y, + "", "타자 연습", + (function() { + location.href = '../../web/client/menu_typing_practice.html'; + }) + ); + if(typingPracticeAppCount === 0) + typingPracticeTabButton.setInputEnabled(false); + + var typingTestTabButton = new TypingTabButton( + TypingTabButton.TEST_BUTTON_POS_X, TypingTabButton.BUTTON_POS_Y, + "", "타자 시험", + (function() { + location.href = '../../web/client/menu_typing_test.html'; + }) + ); + if(typingTestAppCount === 0) + typingTestTabButton.setInputEnabled(false); + + + // typing app buttons + for(var typingButtonIndex = 0; typingButtonIndex < typingAppTotalCount; typingButtonIndex++) { + + var posX = this.getButtonPosX( + typingButtonIndex, typingAppTotalCount + ); + var posY = this.getButtonPosY( + typingButtonIndex, typingAppTotalCount, GameAppButton.BUTTON_LOWER_POS_Y + ); + + var app = appList[typingAppIndex]; + var isKoreanTypingApp = app.AppID < 32 ? true : false; + + var gameAppButton = new GameAppButton( + posX, posY, GameAppButton.TYPE_TYPING_APP, + RoundRectButton.NONE_ICON, // "icon_fullscreen", + // (isKoreanTypingApp ? "(한글)" : "(영문)") + "\n" + app.KoreanName, + app.KoreanName, + { + AppID: app.AppID, + AppName: app.AppName, + KoreanName: app.KoreanName + } + ); + + if(!this.hasApp(app.AppID, activeAppList)) + gameAppButton.setInputEnabled(false); + + typingAppIndex++; + } + }, + + getButtonPosX: function(index, buttonCount) { + var gap = GameAppButton.BUTTON_WIDTH + GameAppButton.BUTTON_GAP; + var maxColumnNum = Math.floor( (game.world.width - GameAppButton.MARGIN_VERTICAL) / gap ); + // console.log("maxColumnNum : " + maxColumnNum); + var rowCount = Math.ceil(buttonCount / maxColumnNum); + // console.log("rowCount : " + rowCount); + + var columnIndex = index % maxColumnNum; + // console.log("columnIndex : " + columnIndex); + var rowIndex = Math.floor(index / maxColumnNum); + // console.log("rowIndex : " + rowIndex); + + var columnCountForThisRow = 0; + if(rowIndex < rowCount - 1) + columnCountForThisRow = maxColumnNum; + else + columnCountForThisRow = buttonCount - (maxColumnNum * rowIndex); + // console.log("columnCountForThisRow : " + columnCountForThisRow); + + var startX = game.world.width / 2 - ( (gap / 2) * (columnCountForThisRow - 1) ); + return startX + gap * columnIndex; + }, + + getButtonPosY: function(index, buttonCount, startPosY) { + var gap = GameAppButton.BUTTON_HEIGHT + GameAppButton.BUTTON_GAP; + var maxColumnNum = Math.floor( (game.world.width - GameAppButton.MARGIN_VERTICAL) / gap ); + // console.log("maxColumnNum : " + maxColumnNum); + var rowCount = Math.ceil(buttonCount / maxColumnNum); + // console.log("rowCount : " + rowCount); + + var rowIndex = Math.floor(index / maxColumnNum); + // console.log("rowIndex : " + rowIndex); + + var startY = startPosY - ( (gap / 2) * (rowCount - 1) ); + return startY + gap * rowIndex; + }, + + loadFailed: function(replyJSON) { + // console.log('login failed, jsonData : ' + JSON.stringify(replyJSON)); + } +} \ No newline at end of file diff --git a/src/game/main_menu/notice_experience_player_text.js b/src/game/main_menu/notice_experience_player_text.js new file mode 100644 index 0000000..2fab1ae --- /dev/null +++ b/src/game/main_menu/notice_experience_player_text.js @@ -0,0 +1,40 @@ +function NoticeExperiencePlayerText() { + this.makeText(game.world.centerX, game.world.centerY - 90, "[ 체험 학생 기능 제한 ]", 28, "#f44"); + this.makeText(game.world.centerX, game.world.centerY - 55, "- 체험용 앱만 실행 가능", 24, "#f44"); + this.makeText(game.world.centerX, game.world.centerY - 25, "- 점수 저장, 랭킹 기능 제한 ", 24, "#f44"); + this.makeText(game.world.centerX, game.world.centerY + 15, "마에스트로 유료 가입시, 모든 컨텐츠 / 기능 사용 가능", 28, "#fc5"); +} + +NoticeExperiencePlayerText.prototype.makeText = function(x, y, text, fontSize, fontColor) { + var newText = game.add.text(x, y, text, this.makeFontStyle(fontSize)); + newText.anchor.set(0.5); + newText.inputEnabled = false; + + // var grd = this.context.createLinearGradient(0, 0, 0, this.height); + // grd.addColorStop(0, '#8ED6FF'); + // grd.addColorStop(1, '#4C6CB3'); + newText.fill = fontColor; // grd; + newText.setShadow(1, 1, 'rgba(0, 0, 0, 0.5)', 1); + newText.stroke = '#000'; + newText.strokeThickness = 5; + + newText.alpha = 1; + var tweenAlpha = game.add.tween(newText); + tweenAlpha.to( { alpha: 0 }, Phaser.Timer.SECOND * 5, Phaser.Easing.Back.In, true); +} + +NoticeExperiencePlayerText.prototype.makeFontStyle = function(fontSize) { + return { font: fontSize + "px Arial", fill: "#f86", align: "left", boundsAlignH: "left", boundsAlignV: "bottom" }; +} + + +NoticeExperiencePlayerText.prototype.destroySelf = function() { + this.destroy(); +} + +NoticeExperiencePlayerText.DEFAULT_TEXT_FONT = { + font: "32px Arial", + boundsAlignH: "center", // left, center. right + boundsAlignV: "middle", // top, middle, bottom + fill: "#fff" +} \ No newline at end of file diff --git a/src/game/main_menu/welcome_player_text.js b/src/game/main_menu/welcome_player_text.js new file mode 100644 index 0000000..a6fa6f1 --- /dev/null +++ b/src/game/main_menu/welcome_player_text.js @@ -0,0 +1,39 @@ +WelcomePlayerText.prototype = Object.create(Phaser.Text.prototype); +WelcomePlayerText.constructor = WelcomePlayerText; + +function WelcomePlayerText(playerName) { + Phaser.Text.call( + this, game, + game.world.width / 2, game.world.height / 2 - 40, + "어서오세요, " + playerName + "님", + WelcomePlayerText.DEFAULT_TEXT_FONT + ); + + this.anchor.set(0.5); + this.inputEnabled = false; + + var grd = this.context.createLinearGradient(0, 0, 0, this.height); + grd.addColorStop(0, '#8ED6FF'); + grd.addColorStop(1, '#4C6CB3'); + this.fill = grd; + this.setShadow(3, 3, 'rgba(0, 0, 0, 0.5)', 2); + this.stroke = '#000'; + this.strokeThickness = 5; + + this.alpha = 1; + var tweenAlpha = game.add.tween(this); + tweenAlpha.to( { alpha: 0 }, Phaser.Timer.SECOND * 2, Phaser.Easing.Back.In, true); + + game.add.existing(this); +} + +WelcomePlayerText.prototype.destroySelf = function() { + this.destroy(); +} + +WelcomePlayerText.DEFAULT_TEXT_FONT = { + font: "60px Arial", + boundsAlignH: "center", // left, center. right + boundsAlignV: "middle", // top, middle, bottom + fill: "#fff" +} \ No newline at end of file diff --git a/src/web/client/main_menu.html b/src/web/client/main_menu.html new file mode 100644 index 0000000..50b065b --- /dev/null +++ b/src/web/client/main_menu.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + 메뉴 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + \ No newline at end of file diff --git a/src/web/php/menu/activate_app.php b/src/web/php/menu/activate_app.php new file mode 100644 index 0000000..af804ab --- /dev/null +++ b/src/web/php/menu/activate_app.php @@ -0,0 +1,52 @@ +prepare($query); + $stmt->bind_param('ii', $maestroID, $appID); + $stmt->execute(); + $stmt->bind_result(); +} + +function get_app_name($appID) { + global $db_conn; + + $query = " + SELECT AppName, KoreanName + FROM app + WHERE AppID = ? + "; + $stmt = $db_conn->prepare($query); + $stmt->bind_param('i', $appID); + $stmt->execute(); + $stmt->bind_result($appName, $koreanName); + $stmt->fetch(); + + $result["AppName"] = $appName; + $result["KoreanName"] = $koreanName; + return $result; +} + +?> \ No newline at end of file