Notes
![]() ![]() Notes - notes.io |
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.ai.pfa.GraphPath;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Graphics;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g3d.utils.AnimationController;
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Plane;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;
import com.badlogic.gdx.math.collision.Ray;
import com.badlogic.gdx.utils.Timer;
import imgui.ImGui;
import imgui.flag.ImGuiWindowFlags;
import imgui.gl3.ImGuiImplGl3;
import imgui.glfw.ImGuiImplGlfw;
import io.swapastack.dunetd.special.Config;
import io.swapastack.dunetd.special.Path;
import io.swapastack.dunetd.special.TileGraph;
import io.swapastack.entities.*;
import net.mgsx.gltf.scene3d.attributes.PBRCubemapAttribute;
import net.mgsx.gltf.scene3d.attributes.PBRTextureAttribute;
import net.mgsx.gltf.scene3d.lights.DirectionalLightEx;
import net.mgsx.gltf.scene3d.scene.Scene;
import net.mgsx.gltf.scene3d.scene.SceneAsset;
import net.mgsx.gltf.scene3d.scene.SceneManager;
import net.mgsx.gltf.scene3d.scene.SceneSkybox;
import net.mgsx.gltf.scene3d.utils.IBLBuilder;
import javax.swing.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
/**
* The GameScreen class.
*
* @author Dennis Jehle
*/
public class GameScreen implements Screen {
private final DuneTD parent;
// GDX GLTF
public SceneManager sceneManager;
private Cubemap diffuseCubemap;
private Cubemap environmentCubemap;
private Cubemap specularCubemap;
private Texture brdfLUT;
private SceneSkybox skybox;
private DirectionalLightEx light;
// libGDX
private PerspectiveCamera camera;
private CameraInputController cameraInputController;
ShapeRenderer debugRenderer;
// 3D models
String basePath = "kenney_gltf/";
String kenneyAssetsFile = "kenney_assets.txt";
String[] kenneyModels;
public HashMap<String, SceneAsset> sceneAssetHashMap;
//Enemies, tiles, bullets and tower lists
public ArrayList<Enemy> enemyList;
public ArrayList<Tower> towers;
public ArrayList<Bullet> bullets;
public GraphPath<Tile> path;
//LIST FOR REMOVE DIED ENEMIES
public ArrayList<Enemy> removeEnemyList;
//remaining mobs
public int remainingMobs = 0;
// Its for checking tower count.
public int knockTowerNum = 0;
//COIN FOR BUILD TOWER. DEFAULT=50
public int coin = 50;
public int point = 0;
public int life = Config.LIFE;
//Selected Tower button for place new tower
private String buildTower = "";
//STORE NEXT WAVE SECONDS
private float nextWaveSecond;
private boolean isLost = false;
//TILE GRAPH FOR PATHFINDING
public TileGraph tileGraph;
// Grid Specifications
public int rows = 7;
public int cols = 12;
//Level
public int level = 1;
// Game Started Controller
private boolean isStarted = false; // By default, game is not started yet
private boolean mobsSpawned = false; // It is for check remaining mobs, if 0 then prepare for new level
// Animation Controllers
AnimationController bossCharacterAnimationController;
AnimationController spaceshipAnimationController;
// SpaiR/imgui-java
public ImGuiImplGlfw imGuiGlfw = new ImGuiImplGlfw();
public ImGuiImplGl3 imGuiGl3 = new ImGuiImplGl3();
long windowHandle;
public GameScreen(DuneTD parent) {
this.parent = parent;
}
/**
* Called when this screen becomes the current screen for a {@link Game}.
* @author Dennis Jehle
*/
@Override
public void show() {
//DEBUG RENDERER FOR GAME
debugRenderer = new ShapeRenderer();
// SpaiR/imgui-java
ImGui.createContext();
windowHandle = ((Lwjgl3Graphics) Gdx.graphics).getWindow().getWindowHandle();
imGuiGlfw.init(windowHandle, true);
imGuiGl3.init("#version 120");
// GDX GLTF - Scene Manager
sceneManager = new SceneManager(64);
// GDX GLTF - Light
light = new DirectionalLightEx();
light.direction.set(1, -3, 1).nor();
light.color.set(Color.WHITE);
sceneManager.environment.add(light);
// GDX GLTF - Image Based Lighting
IBLBuilder iblBuilder = IBLBuilder.createOutdoor(light);
environmentCubemap = iblBuilder.buildEnvMap(1024);
diffuseCubemap = iblBuilder.buildIrradianceMap(256);
specularCubemap = iblBuilder.buildRadianceMap(10);
iblBuilder.dispose();
// GDX GLTF - This texture is provided by the library, no need to have it in your assets.
brdfLUT = new Texture(Gdx.files.classpath("net/mgsx/gltf/shaders/brdfLUT.png"));
// GDX GLTF - Cubemaps
sceneManager.setAmbientLight(1f);
sceneManager.environment.set(new PBRTextureAttribute(PBRTextureAttribute.BRDFLUTTexture, brdfLUT));
sceneManager.environment.set(PBRCubemapAttribute.createSpecularEnv(specularCubemap));
sceneManager.environment.set(PBRCubemapAttribute.createDiffuseEnv(diffuseCubemap));
// GDX GLTF - Skybox
skybox = new SceneSkybox(environmentCubemap);
sceneManager.setSkyBox(skybox);
// Camera
camera = new PerspectiveCamera();
camera.position.set(10.0f, 10.0f, 10.0f);
camera.lookAt(Vector3.Zero);
sceneManager.setCamera(camera);
// Camera Input Controller
cameraInputController = new CameraInputController(camera);
// Set Input Processor
InputMultiplexer inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(cameraInputController);
// TODO: add further input processors if needed
Gdx.input.setInputProcessor(inputMultiplexer);
FileHandle assetsHandle = Gdx.files.internal("kenney_assets.txt");
String fileContent = assetsHandle.readString();
kenneyModels = fileContent.split("\r?\n");
for (int i = 0; i < kenneyModels.length; i++) {
parent.assetManager.load(basePath + kenneyModels[i], SceneAsset.class);
}
parent.assetManager.finishLoading();
// Create scene assets for all loaded models
sceneAssetHashMap = new HashMap<>();
for (int i = 0; i < kenneyModels.length; i++) {
SceneAsset sceneAsset = parent.assetManager.get(basePath + kenneyModels[i], SceneAsset.class);
sceneAssetHashMap.put(kenneyModels[i], sceneAsset);
}
SceneAsset bossCharacter = parent.assetManager.get("faceted_character/scene.gltf");
sceneAssetHashMap.put("faceted_character/scene.gltf", bossCharacter);
SceneAsset enemyCharacter = parent.assetManager.get("cute_cyborg/scene.gltf");
sceneAssetHashMap.put("cute_cyborg/scene.gltf", enemyCharacter);
SceneAsset harvesterCharacter = parent.assetManager.get("spaceship_orion/scene.gltf");
sceneAssetHashMap.put("spaceship_orion/scene.gltf", harvesterCharacter);
SceneAsset portal = parent.assetManager.get("portal/scene.gltf");
sceneAssetHashMap.put("portal/scene.gltf", portal);
SceneAsset knockerTower = parent.assetManager.get("knocker_model/scene.gltf");
sceneAssetHashMap.put("knocker_model/scene.gltf", knockerTower);
SceneAsset sandWorm = parent.assetManager.get("sand/scene.gltf");
sceneAssetHashMap.put("sand/scene.gltf", sandWorm);
SceneAsset bomb = parent.assetManager.get("bomb/scene.gltf");
sceneAssetHashMap.put("bomb/scene.gltf", bomb);
SceneAsset heap = parent.assetManager.get("heap/scene.gltf");
sceneAssetHashMap.put("heap/scene.gltf", heap);
// SETUP ARRAYLISTS
enemyList = new ArrayList<>();
towers = new ArrayList<>();
bullets = new ArrayList<>();
removeEnemyList = new ArrayList<>();
//SETUP SECOND
nextWaveSecond = Config.GAME_START_TIME;
//SET UP TILEGRAPH
tileGraph = new TileGraph(this);
mobsSpawned = false;
createMapExample(sceneManager);
path = tileGraph.findPath(tileGraph.findTileByPos(Config.START_X,Config.START_Z), tileGraph.findTileByPos(Config.TARGET_X,Config.START_Z) );
}
/**
* Called when the screen should render itself.
*
* @author Dennis Jehle
* @param delta - The time in seconds since the last render.
*/
@Override
public void render(float delta) {
// OpenGL - clear color and depth buffer
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
if(isLost)
{
//CHANGE SCREEN IF LOST
parent.changeScreen(ScreenEnum.MENU);
}
//BASICALLY CHECK IF LEVEL LESSER THAN 3, AND LIFE IS HIGHER THAN 0
if(level<3 || life > 0) {
camera.update();
// SET CAMERA FOR DEBUGRENDERER
debugRenderer.setProjectionMatrix(camera.combined);
//Check if started, if not, then prepare other wave
if (isStarted == false && remainingMobs <= 0) {
nextWaveSecond -= delta;
if(nextWaveSecond<0)
nextWaveSecond = 0;
}
//Check if mobs are spawned and remaining mobs
if (mobsSpawned == true && remainingMobs <= 0) {
//THEN GET READY FOR NEW LEVEL
resetGame();
}
//Check if wave second is finished
if (nextWaveSecond <= 0 && isStarted == false) {
isStarted = true;
// Then send wave
sendWave();
}
// UPDATE TOWERS
for (Tower e : towers
) {
e.update(delta);
}
// UPDATE BULLETS
for (Bullet e : bullets
) {
e.update(delta);
}
//UPDATE ENEMIES
for (int i = enemyList.size() - 1; i >= 0; i--) {
enemyList.get(i).update(delta, bullets, towers);
if (enemyList.get(i).DIED) {
sceneManager.removeScene(enemyList.get(i).scene);
sceneManager.removeScene(enemyList.get(i).scene);
if (enemyList.get(i).HEAP) {
enemyList.get(i).scene = new Scene(sceneAssetHashMap.get("heap/scene.gltf").scene);
enemyList.get(i).scene.modelInstance.transform.scale(0.00005f, 0.00005f, 0.00005f).setTranslation(enemyList.get(i).position.cpy());
sceneManager.addScene(enemyList.get(i).scene);
}
}
}
//CHECK IF LIFE IS LESSER THAN 0 AND SHOW DIALOG
if (life <= 0) {
JOptionPane.showMessageDialog(null, "You lost game! Your point: " + point);
isLost = true;
}
// UPDATE TOWERS
// SpaiR/imgui-java
imGuiGlfw.newFrame();
ImGui.newFrame();
// GDX GLTF - update scene manager and render scene
sceneManager.update(delta);
sceneManager.render();
ImGui.begin("TOWERS");
ImGui.text("Spice Coin: " + coin);
if (ImGui.button("Remove Tower")) {
buildTower = "remove";
}
if (!isStarted) {
if (buildTower.isEmpty()) {
if (ImGui.button("Sonic Tower") && coin > Config.SONIC_TOWER_COST) {
buildTower = "sonic";
}
if (ImGui.button("Bomb Tower") && coin > Config.BOMB_TOWER_COST) {
buildTower = "bomb";
}
if (ImGui.button("Cannon Tower") && coin > Config.CANNON_TOWER_COST) {
buildTower = "cannon";
}
} else {
ImGui.text("Please select a tile");
}
} else {
ImGui.text("Wait until wave finished");
if (buildTower.isEmpty()) {
int maxTower = 0;
for (Tower t : towers
) {
if (t instanceof KnockerTower) {
maxTower++;
if (maxTower >= 2)
ImGui.text("You can't create knocker tower more!");
}
}
if (maxTower < 2)
if (ImGui.button("Knocker Tower") && coin > Config.KNOCKER_TOWER_COST) {
buildTower = "knocker";
}
} else {
ImGui.text("Please select a tile");
}
}
ImGui.end();
ImGui.begin("Performance", ImGuiWindowFlags.AlwaysAutoResize);
ImGui.text(String.format(Locale.US, "deltaTime: %1.6f", delta));
ImGui.end();
ImGui.begin("Mobs");
ImGui.setWindowPos(250, 250);
ImGui.text("Remaining Mobs: " + remainingMobs);
ImGui.text("Next wave: " + ((int) nextWaveSecond));
ImGui.text("Level: " + level);
ImGui.text("Highscore Points: " + point);
ImGui.text("Remaining Life: " + life);
ImGui.end();
ImGui.begin("Menu", ImGuiWindowFlags.AlwaysAutoResize);
if (ImGui.button("Back to menu")) {
parent.changeScreen(ScreenEnum.MENU);
}
ImGui.end();
// SpaiR/imgui-java
ImGui.render();
imGuiGl3.renderDrawData(ImGui.getDrawData());
// HANDLE INPUT FOR PUT TOWERS
// IF INPUT IS ON A TILE THEN PUT TOWER
if (Gdx.input.justTouched() && !buildTower.isEmpty()) {
Vector3 position = new Vector3();
Vector3 intersector = new Vector3();
Tile removeTile = null;
for (Tile e : tileGraph.tiles
) {
//GET RAY OF INPUT AND USE POSITION
Ray pickRay = camera.getPickRay(Gdx.input.getX(), Gdx.input.getY());
e.scene.modelInstance.transform.getTranslation(position);
//CHECK IF ON A TILE
if (Intersector.intersectRayBoundsFast(pickRay, position, e.box.getDimensions(new Vector3()))) {
//CHECK IF ON START OR END PORTAL
if ((e.position.x == Config.START_X && e.position.z == Config.START_Z) ||
(e.position.x == Config.TARGET_X && e.position.z == Config.TARGET_Z)) {
System.out.println("YOU CANT PLACE START OR END PORTAL");
return;
}
// SOME JAVA THINGS FOR REMOVE OBJECTS FROM ARRAY
ArrayList<Tower> towersToRemove = new ArrayList<>();
for (Tower t : towers) {
//CHECK IF TOWER IS NOT KNOCKER AND NOT EQUALS TO ANOTHER TOWER POSITION
if (t.actualPosition.equals(position) && buildTower != "knocker") {
if (buildTower == "remove") {
sceneManager.removeScene(t.scene);
towersToRemove.add(t);
if (t instanceof KnockerTower) {
knockTowerNum--;
}
buildTower = "";
System.out.println("YOU REMOVED A TOWER");
return;
}
buildTower = "";
return;
}
System.out.println("TESTING PATH");
//SET PATH
tileGraph.removeConnects(tileGraph.findTileByPos(position.x, position.z));
//CHECK PATH, IF YOUR TOWER CLOSES PATH, THEN DONT ALLOW
path = tileGraph.findPath(tileGraph.findTileByPos(Config.START_X, Config.START_Z), tileGraph.findTileByPos(Config.TARGET_X, Config.START_Z));
System.out.println("PATH CALCULATED, SIZE : " + path.getCount());
if (path.getCount() == 0) {
if (e.position.x - 1 >= 0) {
tileGraph.connectTiles(e, tileGraph.findTileByPos(e.position.x - 1, e.position.z));
}
if (e.position.x + 1 <= cols - 1) {
tileGraph.connectTiles(e, tileGraph.findTileByPos(e.position.x + 1, e.position.z));
}
if (e.position.z + 1 <= rows - 1) {
tileGraph.connectTiles(e, tileGraph.findTileByPos(e.position.x, e.position.z + 1));
}
if (e.position.z - 1 >= 0) {
tileGraph.connectTiles(e, tileGraph.findTileByPos(e.position.x, e.position.z - 1));
}
return;
}
}
Tower tower;
// CHECK CLICKED TOWER SO WE CAN ADD
switch (buildTower) {
case "sonic": {
coin = (int) (coin - Config.SONIC_TOWER_COST);
tower = new SonicTower(this, position);
towers.add(tower);
sceneManager.addScene(tower.scene);
System.out.println("SONIC TOWER CREATED");
break;
}
case "bomb": {
coin = (int) (coin - Config.BOMB_TOWER_COST);
tower = new BombTower(this, position);
towers.add(tower);
sceneManager.addScene(tower.scene);
System.out.println("BOMB TOWER CREATED");
break;
}
case "cannon": {
coin = (int) (coin - Config.CANNON_TOWER_COST);
tower = new CannonTower(this, position);
towers.add(tower);
sceneManager.addScene(tower.scene);
System.out.println("CANNON TOWER CREATED");
break;
}
case "knocker": {
coin = (int) (coin - Config.KNOCKER_TOWER_COST);
tower = new KnockerTower(this, position);
towers.add(tower);
sceneManager.addScene(tower.scene);
for (Enemy f : enemyList) {
//f.setGoal();
}
knockTowerNum++;
if (knockTowerNum >= 2) {
SandWorm sandWorm = new SandWorm(this, position.cpy());
Vector3 lastTowerPos = null;
for (Tower f : towers) {
if (f instanceof KnockerTower) {
if (lastTowerPos == null) {
lastTowerPos = f.actualPosition;
} else {
if (lastTowerPos.x == f.actualPosition.x)
sandWorm.direction = "UP";
else if (lastTowerPos.z == f.actualPosition.z)
sandWorm.direction = "RIGHT";
else
return;
}
}
}
sceneManager.addScene(sandWorm.scene);
towers.add(sandWorm);
}
break;
}
default: {
tower = null;
}
}
buildTower = "";
removeTile = tileGraph.findTileByPos(position.x, position.z);
}
}
tileGraph.removeTiles.add(removeTile);
}
}
}
@Override
public void resize(int width, int height) {
// GDX GLTF - update the viewport
sceneManager.updateViewport(width, height);
}
@Override
public void pause() {
// TODO: implement pause logic if needed
}
@Override
public void resume() {
// TODO: implement resume logic if needed
}
@Override
public void hide() {
// TODO: implement hide logic if needed
}
/**
* This function is for resetting game
*/
public void resetGame(){
//IF YOU FINISH WAVE, THEN APPEAR DIALOG AND RESET GAME
if(level<3) {
JOptionPane.showMessageDialog(null, "You won wave " + level + "! Get ready for other wave! You have " + Config.GAME_START_TIME + " seconds!");
isStarted = false;
nextWaveSecond = Config.GAME_START_TIME;
level++;
mobsSpawned = false;
knockTowerNum = 0;
for (Enemy e : enemyList) {
sceneManager.removeScene(e.scene);
}
enemyList.clear();
ArrayList<Tower> towersToRemove = new ArrayList<>();
for (Tower t : towers
) {
if (t instanceof KnockerTower) {
towersToRemove.add(t);
}
if (t instanceof SandWorm) {
towersToRemove.add(t);
}
if (t.HEAP) {
towersToRemove.add(t);
}
}
for (Tower t : towersToRemove) {
sceneManager.removeScene(t.scene);
}
towers.removeAll(towersToRemove);
}
// IF WAVE HIGHER THAN 3 THEN SHOW ANOTHER DIALOG
else if (level>3)
{
JOptionPane.showMessageDialog(null,"You won game! Your point: " + point);
parent.changeScreen(ScreenEnum.MENU);
isLost = true;
}
}
/**
* This function sends wave of enemies
* It depends on wave number, so no need to give any param
*/
public void sendWave()
{
// WE WILL CREATE A TASK SO IT WILL SEND WAVE
setPath();
new Thread(new Runnable() {
@Override
public void run() {
long currentTime = System.currentTimeMillis();
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
// CLASSIC LEVEL SETUP, JUST GET MULTIPLER WITH LEVEL AND SPAWN BOSS BASED ON LEVEL NUMBER
for(int i = 0; i<Config.BASE_WAVE + (level * Config.MULTIPLER) + level;i++) {
int finalI = i;
Timer.schedule(new Timer.Task() {
@Override
public void run() {
//CREATE ENEMY
/*
Basically, BASE WAVE + (Level* Multipler)
For example, base wave = 10
level = 2 and multipler is 3
then 2*3 = 6 + base wave = 16
and spawn boss for level number
for example if level 2, then spawn 2 boss
*/
if(finalI<Config.BASE_WAVE + level) {
Infantry infantry = new Infantry(GameScreen.this);
sceneManager.addScene(infantry.scene);
enemyList.add(infantry);
//ADD 1 TO REMAINING MOBS WHEN ENEMY SPAWN
remainingMobs++;
}
if(finalI>=Config.BASE_WAVE + level && finalI<Config.BASE_WAVE + (level * Config.MULTIPLER))
{
Harvester harvester = new Harvester(GameScreen.this);
sceneManager.addScene(harvester.scene);
enemyList.add(harvester);
//ADD 1 TO REMAINING MOBS WHEN ENEMY SPAWN
remainingMobs++;
}
if(finalI>=Config.BASE_WAVE + (level * Config.MULTIPLER)) {
Boss boss = new Boss(GameScreen.this);
sceneManager.addScene(boss.scene);
enemyList.add(boss);
//ADD 1 TO REMAINING MOBS WHEN ENEMY SPAWN
remainingMobs++;
mobsSpawned = true;
}
}
},i*Config.SPAWN_TIME/1000);
}
}
});
}
}).start();
}
/**
* This function sets path
*
*/
public void setPath()
{
//HERE IS FOR MAKE A PATH
tileGraph.resetConnections();
for (Tile t: tileGraph.tiles
) {
if (t.position.x - 1 >= 0) {
tileGraph.connectTiles(t, tileGraph.findTileByPos(t.position.x - 1, t.position.z));
}
if (t.position.x + 1 <= cols - 1 ) {
tileGraph.connectTiles(t, tileGraph.findTileByPos(t.position.x + 1, t.position.z));
}
if (t.position.z + 1 <= rows - 1) {
tileGraph.connectTiles(t, tileGraph.findTileByPos(t.position.x, t.position.z + 1));
}
if (t.position.z - 1 >= 0 ) {
tileGraph.connectTiles(t, tileGraph.findTileByPos(t.position.x, t.position.z - 1));
}
}
}
/**
* This function acts as a starting point.
* It generate a simple rectangular map with towers placed on it.
* It doesn't provide any functionality, but it uses some common ModelInstance specific functions.
* Feel free to modify the values and check the results.
*
* @param sceneManager
*/
private void createMapExample(SceneManager sceneManager) {
Vector3 groundTileDimensions = new Vector3();
// Simple way to generate the example map
for (int i = 0; i < rows; i++) {
for (int k = 0; k < cols; k++) {
Tile t = new Tile(this,i,k);
// ADD TO TILEGRAPH
tileGraph.addTile(t);
sceneManager.addScene(t.scene);
tileGraph.movableTiles.add(t);
// it could be useful to store the Scene object reference outside this method
}
}
// HERE IS FOR ADDING NEW PORTALS
Scene start = new Scene(sceneAssetHashMap.get("portal/scene.gltf").scene);
start.modelInstance.transform.setTranslation(Config.START_X,0.5f,Config.START_Z).scale(0.3f,0.3f,0.3f).
rotate(new Vector3(0,0,1),90).rotate(new Vector3(1,0,0),-90);
Scene end = new Scene(sceneAssetHashMap.get("portal/scene.gltf").scene);
end.modelInstance.transform.setTranslation(Config.TARGET_X,0.5f,Config.TARGET_Z).scale(0.3f,0.3f,0.3f)
.rotate(new Vector3(0,0,1),90);
sceneManager.addScene(start);
sceneManager.addScene(end);
setPath();
}
@Override
public void dispose() {
// GDX GLTF - dispose resources
sceneManager.dispose();
for (Enemy e : enemyList
) {
e.dispose();
}
for (Bullet b : bullets
) {
b.dispose();
}
environmentCubemap.dispose();
diffuseCubemap.dispose();
debugRenderer.dispose();
specularCubemap.dispose();
brdfLUT.dispose();
skybox.dispose();
}
}
![]() |
Notes is a web-based application for online taking notes. You can take your notes and share with others people. If you like taking long notes, notes.io is designed for you. To date, over 8,000,000,000+ notes created and continuing...
With notes.io;
- * You can take a note from anywhere and any device with internet connection.
- * You can share the notes in social platforms (YouTube, Facebook, Twitter, instagram etc.).
- * You can quickly share your contents without website, blog and e-mail.
- * You don't need to create any Account to share a note. As you wish you can use quick, easy and best shortened notes with sms, websites, e-mail, or messaging services (WhatsApp, iMessage, Telegram, Signal).
- * Notes.io has fabulous infrastructure design for a short link and allows you to share the note as an easy and understandable link.
Fast: Notes.io is built for speed and performance. You can take a notes quickly and browse your archive.
Easy: Notes.io doesn’t require installation. Just write and share note!
Short: Notes.io’s url just 8 character. You’ll get shorten link of your note when you want to share. (Ex: notes.io/q )
Free: Notes.io works for 14 years and has been free since the day it was started.
You immediately create your first note and start sharing with the ones you wish. If you want to contact us, you can use the following communication channels;
Email: [email protected]
Twitter: http://twitter.com/notesio
Instagram: http://instagram.com/notes.io
Facebook: http://facebook.com/notesio
Regards;
Notes.io Team