diff --git a/README.md b/README.md index 9b56c216..71371e2e 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,30 @@ # Final Project -*Due October 13th (final day of the term)* +Click Cash -For your final project, you'll implement a web application that exhibits understanding of the course materials. -This project should provide an opportunity to both be creative and to pursue individual research and learning goals. +By Matt McGourty -## General description -Your project should consist of a complete Web application, exhibiting facets of the three main sections of the course material: - -- Static web page content and design. You should have a project that is accessible, easily navigable, and features significant content. -- Dynamic behavior implemented with JavaScript (TypeScript is also allowed if your group wants to explore it). -- Server-side programming *using Node.js*. Typically this will take the form of some sort of persistent data (database), authentication, and possibly server-side computation. -- A video (less than five minutes) where each group member explains some aspect of the project. An easy way to produce this video is for you all the groups members to join a Zoom call that is recorded; each member can share their screen when they discuss the project or one member can "drive" the interface while other members narrate (this second option will probably work better.) The video should be posted on YouTube or some other accessible video hosting service. Make sure your video is less than five minutes, but long enough to successfully explain your project and show it in action. There is no minimum video length. +Glitch link: https://finalproject-cs4241.glitch.me/ ## Project ideation -Excellent projects typically serve someone/some group; for this assignment you need to define your users and stakeholders. I encourage you to identify projects that will have impact, either artistically, politically, or in terms of productivity. - -### Deliverables - -#### Form Team (due 9/25) -Students are will work in teams of 3-5 students for the project; teams of two can be approved with the permission of the instructor. Working in teams should help enable you to build a good project in a limited amount of time. Use the `#project-logistics` channel in Discord to pitch ideas for final projects and/or find fellow team members as needed. - -Teams must be in place by end of day on Sunday, September 25th. If you have not identified a team at this point, you will be assigned a team. You will be given some class time on Monday to work on your proposal, but please plan on reserving additional time outside of class as needed. +This project is meant to serve people who like gaming, particularly clicker games, in having fun and being able to play a new game. -#### Proposal (due 9/27) -Provide an outline of your project direction and the names of associated team members. -The outline should have enough detail so that staff can determine if it meets the minimum expectations, or if it goes too far to be reasonable by the deadline. Please include a general description of a project, and list of key technologies/libraries you plan on using (e.g. React, Three.js, Svelte, TypeScript etc.). Two to four paragraps should provide enough level of detail. Name the file proposal.md and submit a pull request by Tuesday, September 27th at 11:59 PM (end of day). Only one pull request is required per team. +## Project Info -There are no other scheduled checkpoints for your project. +1. The game I created is called Click Cash. There is a start screen that tells users to click play. Once users click play, they can click the dollar sign image to earn more in game money. This money can be spent on four different upgrades that cost a various amount, and the cost of each increases as users buy more of the same upgrade. The four upgrades are add autoclicker (gives user +$1 per second automatically), increase per click (extra $1 per click), add business (gives user +$25 per second automatically), and add megaclick (extra $25 per click). The game tracks and displays the user amount of money, money earned per second, and money earned per click. There is also a help page for users who are confused on how the game works or what each upgrade does. -#### Turning in Your Project -Submit a second PR on the final project repo to turn in your app and code. Again, only one pull request per team. +2. No additional instructions should be needed. -Deploy your app, in the form of a webpage, to Glitch/Heroku/Digital Ocean or some other service; it is critical that the application functions correctly wherever you post it. +3. Technologies Used: +Bootstrap -> I used Bootstrap 5 to style parts of the game and also to make the web page responsive, so it looks good and functions on different screen sizes. +Express JS -> I used Express to handle get requests when switching between screens in game. -The README for your second pull request doesn’t need to be a formal report, but it should contain: +4. Challenges +In completing this project, I faced various challenges. -1. A brief description of what you created, and a link to the project itself (two paragraphs of text) -2. Any additional instructions that might be needed to fully use your project (login information etc.) -3. An outline of the technologies you used and how you used them. -4. What challenges you faced in completing the project. -5. What each group member was responsible for designing / developing. -6. A link to your project video. +One challenge was having the game data and front end information update every second based on autoclickers. I was able to do this by creating a JS time with a set interval of 1000, and doing money = money + numAuto (number of money earned auto a second), and then updating the inner HTML of moneyAmount. I also made this function only work when the help page is not open, so the game basically pauses when the user is reading help, and made the button flash different colors so it looks like it is actually being clicked. -Think of 1,3, and 4 in particular in a similar vein to the design / tech achievements for A1—A4… make a case for why what you did was challenging and why your implementation deserves a grade of 100%. +Another challenge I had was getting the values of upgrade costs from innerHTML in order to track previous value before increasing. This was difficult, because I just wanted to get the actual integer value of the price not the "$" or any info after, and the number of digits in the values could potentially change. I was able to solve this by going into the inner HTML and getting a substring that starts at 1 (removes $) and ends at samplePrice.toString().length+1. -## FAQs +6. I was responsible for all work shown in this project. -- **Can I use XYZ framework?** You can use any web-based frameworks or tools available, but for your server programming you need to use Node.js. Your client-side scripting language should be either JavaScript or TypeScript. +7. Youtube Link: https://www.youtube.com/watch?v=WRR4t-gjm0Q&ab_channel=MattMcGourty diff --git a/package.json b/package.json new file mode 100644 index 00000000..a339c2bf --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "finalproject-cs4241", + "version": "0.0.1", + "description": "Final project for CS4241", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.18.2" + }, + "engines": { + "node": "14.x" + }, + "repository": { + "url": "https://glitch.com/edit/#!/final-project-cs4241" + }, + "keywords": [ + "node", + "glitch", + "express" + ] +} diff --git a/public/main.js b/public/main.js new file mode 100644 index 00000000..621c74a7 --- /dev/null +++ b/public/main.js @@ -0,0 +1,203 @@ +var money = 0; +var numAuto = 0; + +var autoPrice = 10; +var perClickPrice = 50; +var businessPrice = 300; +var megaClickPrice = 500; + +var moneyPerClick = 1; +var earnPerSec = 0; + +var timer; +var autoMoneyTime = 1000; + +var dimmed = 0; +var dimmedAuto = 0; + +var helpOpen = 0; + +// Add money when user clicks dollar sign +function addDollar() { + event.preventDefault(); + if (helpOpen == 0) { // No pressing button with help screen open + // Flash button alternating clicks + if (dimmed == 0) { + document.getElementById("addDollarButtonImg").style.opacity = "0.5"; + dimmed = 1; + } else { + document.getElementById("addDollarButtonImg").style.opacity = "1.0"; + dimmed = 0; + } + money = money + moneyPerClick; + document.getElementById("moneyAmount").innerHTML = "$" + money; + toggleButton(); + } +} + +// Add dollar per second +function addAutoClicker() { + event.preventDefault(); + clearInterval(timer); + + // Get cost of autoclicker from html, substring changes depending on digits + var priceStr = document + .getElementById("autoClickerButton") + .innerHTML.substring(1, autoPrice.toString().length + 1); + var price = parseInt(priceStr); + + // Successful buy + if (money >= autoPrice) { + numAuto++; // Add autoclicker + // Decrement total money and update money text + money = money - autoPrice; + document.getElementById("moneyAmount").innerHTML = "$" + money; + + // Increase price of autoclicker and update button text + autoPrice = Math.round(price * 1.2); + document.getElementById("autoClickerButton").innerHTML = + "$" + autoPrice + ": Add Autoclicker"; + + earnPerSec = numAuto / (autoMoneyTime / 1000); + document.getElementById("moneyPerSecond").innerHTML = "$" + earnPerSec; + + toggleButton(); + } + startAutoDollars(); +} + +// Increase amount of money per click by $1 +function increasePerClick() { + event.preventDefault(); + clearInterval(timer); + + var priceStr = document + .getElementById("perClickButton") + .innerHTML.substring(1, perClickPrice.toString().length + 1); + var price = parseInt(priceStr); + if (money >= perClickPrice) { + moneyPerClick++; + money = money - perClickPrice; + document.getElementById("moneyAmount").innerHTML = "$" + money; + perClickPrice = Math.round(price * 1.1); + document.getElementById("perClickButton").innerHTML = + "$" + perClickPrice + ": Increase per Click"; + toggleButton(); + + document.getElementById("moneyPerClick").innerHTML = "$" + moneyPerClick; + } + startAutoDollars(); +} + +// Increase money earned per second by $25 +function addBusiness() { + event.preventDefault(); + clearInterval(timer); + + var priceStr = document + .getElementById("addBusinessButton") + .innerHTML.substring(1, businessPrice.toString().length + 1); + var price = parseInt(priceStr); + + if (money >= businessPrice) { + numAuto += 25; + money = money - businessPrice; + document.getElementById("moneyAmount").innerHTML = "$" + money; + businessPrice = Math.round(price * 1.5); + document.getElementById("addBusinessButton").innerHTML = + "$" + businessPrice + ": Add Business"; + + earnPerSec = numAuto / (autoMoneyTime / 1000); + document.getElementById("moneyPerSecond").innerHTML = "$" + earnPerSec; + + toggleButton(); + } + startAutoDollars(); +} + +// Increase money earned per click by 30 +function addMegaClick() { + event.preventDefault(); + clearInterval(timer); + + var priceStr = document + .getElementById("megaClickButton") + .innerHTML.substring(1, megaClickPrice.toString().length + 1); + var price = parseInt(priceStr); + + if (money >= megaClickPrice) { + moneyPerClick += 25; + money = money - megaClickPrice; + document.getElementById("moneyAmount").innerHTML = "$" + money; + + megaClickPrice = Math.round(price * 1.5); + document.getElementById("megaClickButton").innerHTML = + "$" + megaClickPrice + ": Add MegaClick"; + toggleButton(); + + document.getElementById("moneyPerClick").innerHTML = "$" + moneyPerClick; + } + startAutoDollars(); +} + +// Enable / disable four buttons based on if user can afford them +function toggleButton() { + if (money < autoPrice) + document.getElementById("autoClickerButton").disabled = true; + else if (money >= autoPrice && document.getElementById("autoClickerButton").disabled) + document.getElementById("autoClickerButton").disabled = false; + + if (money < perClickPrice) + document.getElementById("perClickButton").disabled = true; + else if (money >= perClickPrice && document.getElementById("perClickButton").disabled) + document.getElementById("perClickButton").disabled = false; + + if (money < businessPrice) + document.getElementById("addBusinessButton").disabled = true; + else if (money >= businessPrice && document.getElementById("addBusinessButton").disabled) + document.getElementById("addBusinessButton").disabled = false; + + if (money < megaClickPrice) + document.getElementById("megaClickButton").disabled = true; + else if (money >= megaClickPrice && document.getElementById("megaClickButton").disabled) + document.getElementById("megaClickButton").disabled = false; +} + +// Automatically add money every second to user +function startAutoDollars() { + timer = setInterval(function () { + if (helpOpen == 0) { // Make no auto money if help screen open + money = money + numAuto; + document.getElementById("moneyAmount").innerHTML = "$" + money; + toggleButton(); + if (dimmedAuto == 0) { + document.getElementById("addDollarButtonImg").style.opacity = "0.5"; + dimmedAuto = 1; + } else { + document.getElementById("addDollarButtonImg").style.opacity = "1.0"; + dimmedAuto = 0; + } + } + }, autoMoneyTime); +} + +// Click help button once open, click help button twice close +function showHelp() { + var prev = document.getElementById("addDollarButtonImg").style.opacity; + if (helpOpen == 0) { + document.getElementById("helpDiv").style.visibility = "visible"; + document.getElementById("addDollarButtonImg").style.opacity = "0"; + helpOpen = 1; + } else { + document.getElementById("helpDiv").style.visibility = "hidden"; + document.getElementById("addDollarButtonImg").style.opacity = "1"; + helpOpen = 0; + } +} + +// close help +function hideHelp() { + document.getElementById("helpDiv").style.visibility = "hidden"; + document.getElementById("addDollarButtonImg").style.opacity = "1"; + helpOpen = 0; +} diff --git a/public/style.css b/public/style.css new file mode 100644 index 00000000..4949d87d --- /dev/null +++ b/public/style.css @@ -0,0 +1,43 @@ +/* Color pallete from https://muffingroup.com/blog/green-color-palette/ "Waste Not" */ + +body { + background-color:#faf6ed; +} + +/* Do not let button img be selected or dragged */ +#addDollarButtonImg { + user-select: none; + -moz-user-select: none; + -webkit-user-drag: none; + -webkit-user-select: none; + -ms-user-select: none; +} + +#addDollarButtonImg:hover { + cursor:grab; + +} + +#helpDiv { + position:absolute; + top:3%; + left:50%; + text-align:center; + transform:translate(-50%, 50%); + opacity:97%; + background-color:#e6ca51; + visibility:hidden; +} + +#mainHeading, #mainHeadingTop { + background-color:#0f9015; +} + +#autoClickerButton, #perClickButton, #addBusinessButton, #megaClickButton { + background-color:#b25e7e; + width:250px; +} + +#helpButton { + background-color: #e6ca51; +} diff --git a/server.js b/server.js new file mode 100644 index 00000000..7b81387a --- /dev/null +++ b/server.js @@ -0,0 +1,21 @@ +const express = require("express"); + +const app = express(); + +app.use(express.static("public")); + +app.use(express.json()); +app.use(express.urlencoded( {extended: false} )); + +app.get("/", function(request, response) { + response.sendFile(__dirname + "/views/start.html"); +}); + +app.get("/tapmoney", function(request, response) { + response.sendFile(__dirname + "/views/index.html"); +}); + +// listen for requests :) +const listener = app.listen(process.env.PORT, function() { + console.log("Your app is listening on port " + listener.address().port); +}); diff --git a/views/index.html b/views/index.html new file mode 100644 index 00000000..fe0558cb --- /dev/null +++ b/views/index.html @@ -0,0 +1,132 @@ + + +
+ + + + + + + + + + +Earned per second:
+$0
+Earned per click:
+$1
+Click the green dollar sign and earn money!
+
+ Add Autoclicker: +$1/second automatically
+ Increase per Click +$1/click
+ Add Business +$25/second automically
+ Add MegaClick +$25/click
+