updated dependencies, and improved rss feed summary
All checks were successful
Web/pipeline/head This commit looks good
All checks were successful
Web/pipeline/head This commit looks good
This commit is contained in:
parent
ade56d6663
commit
67e0e74569
35 changed files with 3447 additions and 3447 deletions
|
@ -4,17 +4,17 @@ GEM
|
|||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.1.9)
|
||||
em-websocket (0.5.2)
|
||||
concurrent-ruby (1.1.10)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0.6.0)
|
||||
http_parser.rb (~> 0)
|
||||
eventmachine (1.2.7-x64-mingw32)
|
||||
ffi (1.15.3-x64-mingw32)
|
||||
ffi (1.15.5-x64-mingw32)
|
||||
forwardable-extended (2.6.0)
|
||||
http_parser.rb (0.6.0)
|
||||
i18n (1.8.10)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.11.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (4.2.0)
|
||||
jekyll (4.2.2)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
|
@ -29,35 +29,35 @@ GEM
|
|||
rouge (~> 3.0)
|
||||
safe_yaml (~> 1.0)
|
||||
terminal-table (~> 2.0)
|
||||
jekyll-feed (0.15.1)
|
||||
jekyll-feed (0.16.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-sass-converter (2.1.0)
|
||||
jekyll-sass-converter (2.2.0)
|
||||
sassc (> 2.0.1, < 3.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
kramdown (2.3.1)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.5.1)
|
||||
listen (3.7.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
mercenary (0.4.0)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (4.0.6)
|
||||
rb-fsevent (0.11.0)
|
||||
public_suffix (4.0.7)
|
||||
rb-fsevent (0.11.1)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.2.5)
|
||||
rouge (3.26.0)
|
||||
rouge (3.29.0)
|
||||
safe_yaml (1.0.5)
|
||||
sassc (2.4.0-x64-mingw32)
|
||||
ffi (~> 1.9)
|
||||
terminal-table (2.0.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
unicode-display_width (1.7.0)
|
||||
unicode-display_width (1.8.0)
|
||||
webrick (1.7.0)
|
||||
|
||||
PLATFORMS
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<div class="card bg-light blog-entry rounded-0 {% for tag in include.post.tags %} blog-tag-{{ tag | slugify}} {% endfor %}">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title blog-title"><a class="blog-button" href="{{ include.post.url }}">{{ include.post.title }}</a></h4>
|
||||
<div class="card-text blog-summary">{{ include.post.summary }}</div>
|
||||
<span class="text-muted project-status">{{ include.post.date | date_to_string }}</span>
|
||||
<span class="text-muted blog-cat">{{ include.post.tags | join: ", " }}</span>
|
||||
</div>
|
||||
<div class="card bg-light blog-entry rounded-0 {% for tag in include.post.tags %} blog-tag-{{ tag | slugify}} {% endfor %}">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title blog-title"><a class="blog-button" href="{{ include.post.url }}">{{ include.post.title }}</a></h4>
|
||||
<div class="card-text blog-summary">{{ include.post.description }}</div>
|
||||
<span class="text-muted project-status">{{ include.post.date | date_to_string }}</span>
|
||||
<span class="text-muted blog-cat">{{ include.post.tags | join: ", " }}</span>
|
||||
</div>
|
||||
</div>
|
|
@ -1,40 +1,40 @@
|
|||
---
|
||||
layout: default
|
||||
nav: nav/blognav.html
|
||||
---
|
||||
|
||||
{% if page.book %}
|
||||
<link rel="stylesheet" href="/style/book.css">
|
||||
{% else %}
|
||||
<script>
|
||||
let style = dark ? "monokai" : "friendly";
|
||||
addStyle(`https://cdn.jsdelivr.net/gh/richleland/pygments-css@master/${style}.css`);
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<div class="list-display rounded">
|
||||
<div class="blog-isolated">
|
||||
<h1>{{ page.title }}</h1>
|
||||
|
||||
{% if page.archived %}
|
||||
<p>🧓 <em>This post has been archived.</em></p>
|
||||
{% endif %}
|
||||
|
||||
{% if page.mature %}
|
||||
<p>⚠️ <em>This post contains mature content.</em></p>
|
||||
{% endif %}
|
||||
|
||||
{% if page.reedsy %}
|
||||
<p>📘 <em>This story was inspired by a Reedsy Prompt and submitted to their competition. As such, it has also been published on <a href="{{ page.reedsy }}">their website</a>.</em></p>
|
||||
{% endif %}
|
||||
|
||||
<div class="post-content">
|
||||
{{ content }}
|
||||
</div>
|
||||
|
||||
<span class="text-muted project-status blog-isolated-status">{{ page.date | date_to_string }}</span>
|
||||
{% if page.discuss %}
|
||||
🧵 <a href="{{ page.discuss }}" class="blog-discuss">Discuss this post</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
---
|
||||
layout: default
|
||||
nav: nav/blognav.html
|
||||
---
|
||||
|
||||
{% if page.book %}
|
||||
<link rel="stylesheet" href="/style/book.css">
|
||||
{% else %}
|
||||
<script>
|
||||
let style = dark ? "monokai" : "friendly";
|
||||
addStyle(`https://cdn.jsdelivr.net/gh/richleland/pygments-css@master/${style}.css`);
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<div class="list-display rounded">
|
||||
<div class="blog-isolated">
|
||||
<h1>{{ page.title }}</h1>
|
||||
|
||||
{% if page.archived %}
|
||||
<p>🧓 <em>This post has been archived.</em></p>
|
||||
{% endif %}
|
||||
|
||||
{% if page.mature %}
|
||||
<p>⚠️ <em>This post contains mature content.</em></p>
|
||||
{% endif %}
|
||||
|
||||
{% if page.reedsy %}
|
||||
<p>📘 <em>This story was inspired by a Reedsy Prompt and submitted to their competition. As such, it has also been published on <a href="{{ page.reedsy }}">their website</a>.</em></p>
|
||||
{% endif %}
|
||||
|
||||
<div class="post-content">
|
||||
{{ content }}
|
||||
</div>
|
||||
|
||||
<span class="text-muted project-status blog-isolated-status">{{ page.date | date_to_string }}</span>
|
||||
{% if page.discuss %}
|
||||
🧵 <a href="{{ page.discuss }}" class="blog-discuss">Discuss this post</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
|
@ -1,61 +1,61 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>{{ page.title }}</title>
|
||||
<meta name="author" content="Ellpeck">
|
||||
<meta name="description" content="{{ page.summary }}">
|
||||
<meta name="keywords" content="Ellpeck, Actually Additions, Rock Bottom, Programming, Minecraft, Game Development, Nature's Aura, C#, Java, Blog, Tutorial, Foe Frenzy">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto&display=swap">
|
||||
|
||||
<link rel="stylesheet" href="/style/style.css">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
|
||||
<meta property="og:title" content="{{ page.title }}">
|
||||
<meta property="og:description" content="{{ page.summary }}">
|
||||
<meta property="og:image" content="https://ellpeck.de/res/logoSmall.png">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@Ellpeck">
|
||||
<meta name="twitter:creator" content="@Ellpeck">
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script src="/scripts/util.js"></script>
|
||||
<script src="/scripts/main.js"></script>
|
||||
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XC0W9LJMCJ"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-XC0W9LJMCJ');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body data-spy="scroll" data-target="#navbar">
|
||||
{% include nav/navbar.html %}
|
||||
|
||||
<!-- Content -->
|
||||
<div class="container main">
|
||||
<!-- Cookie notification -->
|
||||
<div id="cookieinfo"></div>
|
||||
<script src="/scripts/cookieinfo.js"></script>
|
||||
<div id="main">
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include footer.html %}
|
||||
</body>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>{{ page.title }}</title>
|
||||
<meta name="author" content="Ellpeck">
|
||||
<meta name="description" content="{{ page.description }}">
|
||||
<meta name="keywords" content="Ellpeck, Actually Additions, Programming, Minecraft, Game Development, Nature's Aura, C#, Java, Blog, Tutorial, Pretty Pipes, Tiny Life, Ellpeck Games">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto&display=swap">
|
||||
|
||||
<link rel="stylesheet" href="/style/style.css">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
|
||||
<meta property="og:title" content="{{ page.title }}">
|
||||
<meta property="og:description" content="{{ page.description }}">
|
||||
<meta property="og:image" content="https://ellpeck.de/res/logoSmall.png">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@Ellpeck">
|
||||
<meta name="twitter:creator" content="@Ellpeck">
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script src="/scripts/util.js"></script>
|
||||
<script src="/scripts/main.js"></script>
|
||||
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XC0W9LJMCJ"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-XC0W9LJMCJ');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body data-spy="scroll" data-target="#navbar">
|
||||
{% include nav/navbar.html %}
|
||||
|
||||
<!-- Content -->
|
||||
<div class="container main">
|
||||
<!-- Cookie notification -->
|
||||
<div id="cookieinfo"></div>
|
||||
<script src="/scripts/cookieinfo.js"></script>
|
||||
<div id="main">
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include footer.html %}
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,15 +1,15 @@
|
|||
---
|
||||
layout: blog
|
||||
title: ✨ Blogs are Cool, I Think
|
||||
summary: The first post and how I created it
|
||||
tags: [Miscellaneous]
|
||||
discuss: https://twitter.com/Ellpeck/status/1096937184601538566
|
||||
archived: true
|
||||
---
|
||||
|
||||
So I've been wanting to make a blog for a while, but never found the motivation to do so. Especially with all of the blog softwares out there, it was hard to figure out which one to use to make it fit this website and its design nicely.
|
||||
I didn't really want to make a whole different page just for the blog because it would kind of throw the design off, so I took some inspiration from [Vazkii's blog](https://vazkii.us/#blog) and made mine work in a similar fashion. This still made it work with the single page design.
|
||||
|
||||
Now because I'm not good with PHP at all, I actually made this entire thing using only JavaScript. It's.. a bit of a mess, honestly, but it works.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: ✨ Blogs are Cool, I Think
|
||||
description: The first post and how I created it
|
||||
tags: [Miscellaneous]
|
||||
discuss: https://twitter.com/Ellpeck/status/1096937184601538566
|
||||
archived: true
|
||||
---
|
||||
|
||||
So I've been wanting to make a blog for a while, but never found the motivation to do so. Especially with all of the blog softwares out there, it was hard to figure out which one to use to make it fit this website and its design nicely.
|
||||
I didn't really want to make a whole different page just for the blog because it would kind of throw the design off, so I took some inspiration from [Vazkii's blog](https://vazkii.us/#blog) and made mine work in a similar fashion. This still made it work with the single page design.
|
||||
|
||||
Now because I'm not good with PHP at all, I actually made this entire thing using only JavaScript. It's.. a bit of a mess, honestly, but it works.
|
||||
|
||||
So here it is. Expect me to, very occasionally, do a post about one or the other random thing. *Enjoy!*
|
|
@ -1,52 +1,52 @@
|
|||
---
|
||||
layout: blog
|
||||
title: ⚙️ Why You Should Mod Minecraft
|
||||
summary: About what makes Minecraft modding great and why you should probably try it if you enjoy programming
|
||||
tags: [Minecraft, Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1097177774337462272
|
||||
---
|
||||
|
||||
So... for the last couple of years, the main thing I've been doing in my free time is game development and modding Minecraft, but the latter far more often and more consistently. I've learned a lot while doing this, but not only when it comes to programming and game development, but also when it comes to a lot of other things.
|
||||
So in this post, I want to introduce you to what's so great about Minecraft modding and, honestly, why you should try doing it as well.
|
||||
|
||||
# Programming Experience
|
||||
Now, first and foremost, and I think this is definitely one of the most obvious point: It improves your programming experience by quite a bit. Both in the "understanding the language" department, but also, it helps you to do a couple of things that you'll need if you want to deal with anything that other people have made:
|
||||
- Understanding someone else's codebase and learning to navigate code that someone else has made, both documented and undocumented
|
||||
- The beauty of learning how annoying it is to see code that's made in a way that makes it *so unbelievably hard* to expand it, to build on it, and learning that, when making your own code, you most definitely shouldn't do it like that.
|
||||
- Learning to make something fit well with something other people have made. I'm sure this is also a useful skill to have in a job that includes team efforts: The same way a paper should have a unified style, it's also not very nice to have high resolution textures in a mod for a game that has a very primitive artstyle.
|
||||
|
||||
# Easily Creating Things
|
||||
When creating your own game, I've personally found that it's pretty hard to get it off the ground at the start, because all you can see for the first couple of days are missing textures, placeholders, a missing main menu, janky controls and so on. When you're making a mod for any game, but especially for Minecraft, you can create a single, small feature and then instantly start using it together with all of the other features that the game already provides for you.
|
||||
|
||||
It's so much easier to get excited and satisfied about something you've made when it doesn't take ages for it to actually look good in its intended environment - making a mod for a game is perfect for that.
|
||||
|
||||
# Meeting Amazing People
|
||||
This is something that definitely comes a bit later down the line, at least it did for me, but it's also something that's been really, really important to me. Through modding Minecraft, and especially by making [Actually Additions](https://minecraft.curseforge.com/projects/actually-additions), I've met so many amazing people and made a huge amount of new friends.
|
||||
And not only that, I've also met a lot of people that I really look(ed) up to and respect(ed), and then noticed how down to earth and nice they actually are (because after all, they're also just people): Direwolf20, Vazkii and so many other people became my friends because it's easy to get along well with someone that shares the same interests as you, especially when it's an interest as passionate as the Minecraft Modding community.
|
||||
|
||||
# Being Validated by Thousands
|
||||
This is one of the most important bits for me, honestly. I have pretty low self esteem (as a lot of introverted people on the internet do, I imagine), and it's hard for me to be proud of something that I've created.
|
||||
But through the mods I've made, especially Actually Additions and recently also [Nature's Aura](https://minecraft.curseforge.com/projects/natures-aura), I've been shown by so many people, both friends and complete strangers, that the stuff I make seems to be worth quite a lot to quite a lot of people, and that they're passionate about my work, some maybe even more passionate than I am about it myself.
|
||||
|
||||
It feels so good to make something and to see people downloading it, people playing with it, people making videos about it and saying how nice they think it is. Trying to be validated isn't "seeking attention", it's good for you, because it makes you feel like you're worth a lot. Because you are.
|
||||
|
||||
# Learning to Deal With Criticism
|
||||
Also a big thing for me for sure. Because of my previously mentioned low self esteem, it's been pretty hard for me to accept and deal with people saying that they dislike something that I've created.
|
||||
|
||||
But in the Minecraft modding community, oh boy, it's a *huge* thing. The first thing you'll get to hear about any new mod you publish is how it's "*totally a ripoff of Thaumcraft and Botania*" and "*this is just Extra Utilities, but worse*", and so on, and so forth. And.. at first, it can be quite demotivating, to say the least, because it sucks that people compare your thing to someone else's thing, despite the fact that you put at least an equal amount of work in it, and despite the fact that it deserves the same amount of respect as that other thing.
|
||||
But that's just the way people are, and sooner or later, you have to learn to accept that. And you will. Positive people will still be there, and the stuff you've made will still be loved by a lot of them.
|
||||
|
||||
And it's not all bad either, in fact, the opposite is true: There are a *lot* of people that give you constructive criticism: "*I enjoyed this, but I think x, y and z could be changed and it would be even better.*" If you're the kind of person that says this, then you're a winner, because this helps not only the thing you're commenting on, but also the person that's made the thing: Now they know what you like, what you don't like, but most importantly: *How to fix it for you*. And the best thing is: You as the creator don't even have to listen to them if you disagree! They'll probably understand, because they're nice enough not to be dicks like the people I talked about before.
|
||||
|
||||
So keep on going, no matter what people say, because you're probably awesome.
|
||||
|
||||
# Basically No Obligations
|
||||
When making a game, or a "real" product in general, a lot of the time, you're bound to certain obligations: Either it's legal ones, or maybe you've done a Kickstarter, maybe the thing you make actually costs you quite a bit of money because you have a whole development team, stuff like that.
|
||||
Well with Minecraft modding, the only thing you have to deal with is people asking you when you'll *finally* update to the next version. But if you're sick of that, or sick of anything else, you can just stop, take a break, and do something else entirely for a while.
|
||||
|
||||
People might judge, but the important thing is: They don't have a right to judge, because you can do whatever you want. It's a hobby thing, so it's your thing.
|
||||
|
||||
# So yea,
|
||||
this is all of the stuff I could think of that inspires me to keep going with Minecraft Modding. It's been a really awesome journey so far and I'm excited to keep going, to create more things and to see more things that other people created.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: ⚙️ Why You Should Mod Minecraft
|
||||
description: About what makes Minecraft modding great and why you should probably try it if you enjoy programming
|
||||
tags: [Minecraft, Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1097177774337462272
|
||||
---
|
||||
|
||||
So... for the last couple of years, the main thing I've been doing in my free time is game development and modding Minecraft, but the latter far more often and more consistently. I've learned a lot while doing this, but not only when it comes to programming and game development, but also when it comes to a lot of other things.
|
||||
So in this post, I want to introduce you to what's so great about Minecraft modding and, honestly, why you should try doing it as well.
|
||||
|
||||
# Programming Experience
|
||||
Now, first and foremost, and I think this is definitely one of the most obvious point: It improves your programming experience by quite a bit. Both in the "understanding the language" department, but also, it helps you to do a couple of things that you'll need if you want to deal with anything that other people have made:
|
||||
- Understanding someone else's codebase and learning to navigate code that someone else has made, both documented and undocumented
|
||||
- The beauty of learning how annoying it is to see code that's made in a way that makes it *so unbelievably hard* to expand it, to build on it, and learning that, when making your own code, you most definitely shouldn't do it like that.
|
||||
- Learning to make something fit well with something other people have made. I'm sure this is also a useful skill to have in a job that includes team efforts: The same way a paper should have a unified style, it's also not very nice to have high resolution textures in a mod for a game that has a very primitive artstyle.
|
||||
|
||||
# Easily Creating Things
|
||||
When creating your own game, I've personally found that it's pretty hard to get it off the ground at the start, because all you can see for the first couple of days are missing textures, placeholders, a missing main menu, janky controls and so on. When you're making a mod for any game, but especially for Minecraft, you can create a single, small feature and then instantly start using it together with all of the other features that the game already provides for you.
|
||||
|
||||
It's so much easier to get excited and satisfied about something you've made when it doesn't take ages for it to actually look good in its intended environment - making a mod for a game is perfect for that.
|
||||
|
||||
# Meeting Amazing People
|
||||
This is something that definitely comes a bit later down the line, at least it did for me, but it's also something that's been really, really important to me. Through modding Minecraft, and especially by making [Actually Additions](https://minecraft.curseforge.com/projects/actually-additions), I've met so many amazing people and made a huge amount of new friends.
|
||||
And not only that, I've also met a lot of people that I really look(ed) up to and respect(ed), and then noticed how down to earth and nice they actually are (because after all, they're also just people): Direwolf20, Vazkii and so many other people became my friends because it's easy to get along well with someone that shares the same interests as you, especially when it's an interest as passionate as the Minecraft Modding community.
|
||||
|
||||
# Being Validated by Thousands
|
||||
This is one of the most important bits for me, honestly. I have pretty low self esteem (as a lot of introverted people on the internet do, I imagine), and it's hard for me to be proud of something that I've created.
|
||||
But through the mods I've made, especially Actually Additions and recently also [Nature's Aura](https://minecraft.curseforge.com/projects/natures-aura), I've been shown by so many people, both friends and complete strangers, that the stuff I make seems to be worth quite a lot to quite a lot of people, and that they're passionate about my work, some maybe even more passionate than I am about it myself.
|
||||
|
||||
It feels so good to make something and to see people downloading it, people playing with it, people making videos about it and saying how nice they think it is. Trying to be validated isn't "seeking attention", it's good for you, because it makes you feel like you're worth a lot. Because you are.
|
||||
|
||||
# Learning to Deal With Criticism
|
||||
Also a big thing for me for sure. Because of my previously mentioned low self esteem, it's been pretty hard for me to accept and deal with people saying that they dislike something that I've created.
|
||||
|
||||
But in the Minecraft modding community, oh boy, it's a *huge* thing. The first thing you'll get to hear about any new mod you publish is how it's "*totally a ripoff of Thaumcraft and Botania*" and "*this is just Extra Utilities, but worse*", and so on, and so forth. And.. at first, it can be quite demotivating, to say the least, because it sucks that people compare your thing to someone else's thing, despite the fact that you put at least an equal amount of work in it, and despite the fact that it deserves the same amount of respect as that other thing.
|
||||
But that's just the way people are, and sooner or later, you have to learn to accept that. And you will. Positive people will still be there, and the stuff you've made will still be loved by a lot of them.
|
||||
|
||||
And it's not all bad either, in fact, the opposite is true: There are a *lot* of people that give you constructive criticism: "*I enjoyed this, but I think x, y and z could be changed and it would be even better.*" If you're the kind of person that says this, then you're a winner, because this helps not only the thing you're commenting on, but also the person that's made the thing: Now they know what you like, what you don't like, but most importantly: *How to fix it for you*. And the best thing is: You as the creator don't even have to listen to them if you disagree! They'll probably understand, because they're nice enough not to be dicks like the people I talked about before.
|
||||
|
||||
So keep on going, no matter what people say, because you're probably awesome.
|
||||
|
||||
# Basically No Obligations
|
||||
When making a game, or a "real" product in general, a lot of the time, you're bound to certain obligations: Either it's legal ones, or maybe you've done a Kickstarter, maybe the thing you make actually costs you quite a bit of money because you have a whole development team, stuff like that.
|
||||
Well with Minecraft modding, the only thing you have to deal with is people asking you when you'll *finally* update to the next version. But if you're sick of that, or sick of anything else, you can just stop, take a break, and do something else entirely for a while.
|
||||
|
||||
People might judge, but the important thing is: They don't have a right to judge, because you can do whatever you want. It's a hobby thing, so it's your thing.
|
||||
|
||||
# So yea,
|
||||
this is all of the stuff I could think of that inspires me to keep going with Minecraft Modding. It's been a really awesome journey so far and I'm excited to keep going, to create more things and to see more things that other people created.
|
||||
|
||||
Thanks for reading! <3
|
|
@ -1,27 +1,27 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 🔥 Kindling the Reading Flame
|
||||
summary: About the Kindle, Harry Potter and what I like and dislike about them
|
||||
tags: [Reading]
|
||||
discuss: https://twitter.com/Ellpeck/status/1109102077911973888
|
||||
---
|
||||
|
||||
Recently, my boyfriend gave me his old Amazon Kindle (because he got one of the newer models). This inspired me, after about four or five years of not really picking up a book outside of school, to start reading for fun again. The first book that I "picked up" was Harry Potter and the.. stone.. of the wise ("Harry Potter and the Philosopher's Stone" apparently).
|
||||
|
||||
# The book
|
||||
I've never written a book review before, but since Harry Potter is kind of a really popular genre and this is the first time I read one of the books, I wanted to give my opinion on it.
|
||||
|
||||
Now usually, I don't really enjoy the fantasy genre. Something about it is just a bit uninteresting to me, and I don't necessarily enjoy reading something that's unrelated to (my) reality. I usually need entertainment to be somewhat relatable to me and my life, and fantasy and science fiction don't always do that for me; I don't really enjoy things like Star Wars, but I do enjoy, for example, the Netflix show Black Mirror, because it touches topics that I do come in contact with in my own life.
|
||||
But because the first Harry Potter book introduced the entire thing in such a great way, making the reader follow along with Harry's journey of _also_ figuring out all of the magic stuff that is new to both him and the reader, it felt like a lot better of an introduction to me.
|
||||
|
||||
Reading the first three quarters or so of the book, I honestly had a blast. The story was being told so well and all of the details and emotions were depicted so extensively, the places were described with a depth that made me be able to envision them perfectly in my head.
|
||||
But then, to my (negative) surprise, suddenly, towards the last couple of chapters of the book, the tone shifted. All of a sudden, the story was being told in such a rushed, quick way; especially what should've been the climax of the book. To me, it felt like the author was getting scared of missing her deadline and stopped writing in the way that I had started to love so much.
|
||||
|
||||
I would definitely say that I enjoyed the book (which is saying quite a lot, because fantasy is definitely not my kind of genre), and I plan on also reading the other entries in the series, but to me, it felt like the later in the book I was, the more the quality of what I was reading was declining, which was such a bummer to me because J.K. Rowling seems to be a _really_ good author.
|
||||
|
||||
_Also, regarding the stuff that's happening with whatever J.K. is saying right now: If she or anyone else thinks it's okay to retroactively pretend like there's diversity where there simply isn't any: In my opinion, it's not okay. Just accept that your writing in that regard just isn't up to the standard of what it should be in the 21st century. Characters shouldn't be gay, black or another minority for the sake of "showing diversity" or "making a statement", but because diversity like that just happens to exist in the real world._
|
||||
|
||||
# The Kindle
|
||||
There's honestly not much to say about the Kindle, because everything that I could say can be easily summed up into this: _I absolutely love it_. It's one of the older generation Paperwhites (maybe even the first one, I'm not sure), and the e-ink is amazing, the menus are easy to navigate, being able to change the font is great. It's just all round an awesome experience, especially because, with Amazon Prime, which pretty much everyone seems to have, you have Prime Reading, which allows you to read quite a big amount of books for free (without even having to get Kindle Unlimited).
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 🔥 Kindling the Reading Flame
|
||||
description: About the Kindle, Harry Potter and what I like and dislike about them
|
||||
tags: [Reading]
|
||||
discuss: https://twitter.com/Ellpeck/status/1109102077911973888
|
||||
---
|
||||
|
||||
Recently, my boyfriend gave me his old Amazon Kindle (because he got one of the newer models). This inspired me, after about four or five years of not really picking up a book outside of school, to start reading for fun again. The first book that I "picked up" was Harry Potter and the.. stone.. of the wise ("Harry Potter and the Philosopher's Stone" apparently).
|
||||
|
||||
# The book
|
||||
I've never written a book review before, but since Harry Potter is kind of a really popular genre and this is the first time I read one of the books, I wanted to give my opinion on it.
|
||||
|
||||
Now usually, I don't really enjoy the fantasy genre. Something about it is just a bit uninteresting to me, and I don't necessarily enjoy reading something that's unrelated to (my) reality. I usually need entertainment to be somewhat relatable to me and my life, and fantasy and science fiction don't always do that for me; I don't really enjoy things like Star Wars, but I do enjoy, for example, the Netflix show Black Mirror, because it touches topics that I do come in contact with in my own life.
|
||||
But because the first Harry Potter book introduced the entire thing in such a great way, making the reader follow along with Harry's journey of _also_ figuring out all of the magic stuff that is new to both him and the reader, it felt like a lot better of an introduction to me.
|
||||
|
||||
Reading the first three quarters or so of the book, I honestly had a blast. The story was being told so well and all of the details and emotions were depicted so extensively, the places were described with a depth that made me be able to envision them perfectly in my head.
|
||||
But then, to my (negative) surprise, suddenly, towards the last couple of chapters of the book, the tone shifted. All of a sudden, the story was being told in such a rushed, quick way; especially what should've been the climax of the book. To me, it felt like the author was getting scared of missing her deadline and stopped writing in the way that I had started to love so much.
|
||||
|
||||
I would definitely say that I enjoyed the book (which is saying quite a lot, because fantasy is definitely not my kind of genre), and I plan on also reading the other entries in the series, but to me, it felt like the later in the book I was, the more the quality of what I was reading was declining, which was such a bummer to me because J.K. Rowling seems to be a _really_ good author.
|
||||
|
||||
_Also, regarding the stuff that's happening with whatever J.K. is saying right now: If she or anyone else thinks it's okay to retroactively pretend like there's diversity where there simply isn't any: In my opinion, it's not okay. Just accept that your writing in that regard just isn't up to the standard of what it should be in the 21st century. Characters shouldn't be gay, black or another minority for the sake of "showing diversity" or "making a statement", but because diversity like that just happens to exist in the real world._
|
||||
|
||||
# The Kindle
|
||||
There's honestly not much to say about the Kindle, because everything that I could say can be easily summed up into this: _I absolutely love it_. It's one of the older generation Paperwhites (maybe even the first one, I'm not sure), and the e-ink is amazing, the menus are easy to navigate, being able to change the font is great. It's just all round an awesome experience, especially because, with Amazon Prime, which pretty much everyone seems to have, you have Prime Reading, which allows you to read quite a big amount of books for free (without even having to get Kindle Unlimited).
|
||||
|
||||
Seriously, if you enjoy reading, but don't enjoy carrying heavy books around with you while you're traveling, I really think you should get a Kindle.
|
|
@ -1,70 +1,70 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 🗡️ Small Projects
|
||||
summary: Why creating a small, unplanned project is sometimes good for you
|
||||
tags: [Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1123651624201871360
|
||||
---
|
||||
|
||||
As it turns out, I struggle a lot with maintaining interest and motivation for working on bigger projects like my [other game](https://rockbottom.ellpeck.de/) or my Minecraft mods. However, an easy fix for that would be to just start less big projects and focus more on smaller ones, like **Foe Frenzy**. Foe Frenzy is a game I've been working on for about a month now.
|
||||
|
||||
<img src="/blog/res/small_projects/contrib.png" width="100%">
|
||||
|
||||
The basic gameplay is finished, as is enough content for my friends to have been testing it for the last week or so and saying that they enjoy it quite a bit, both visually and gameplay-wise. I thought I'd make a blog post about my process of working on it, showing what it's about and what I did this time around to make sure that I don't get burnt out with it.
|
||||
|
||||
<img src="/blog/res/small_projects/overview.png" width="100%">
|
||||
|
||||
_Foe Frenzy is a fast-paced fighting game where you battle up to three of your friends with random, short-lasting items in an attempt to be the last survivor._
|
||||
|
||||
# The Artstyle
|
||||
Not every developer has this problem, but I know a lot do: The inability to make good-looking art. Well, I have this same problem too.
|
||||
A lot of times, I'll find myself getting stuck on making art for my game projects and getting burnt out through trying too hard to force myself to make good-looking art.
|
||||
|
||||
So, this time around, what I did instead of doing that all over again, I just decided to go with _simple art_ instead. For example, as you can see, all the tiles in the world only have 8x8 pixels, and all of them follow a really simple pattern: The top and left side are slightly darker, giving the world a really tiled feel and making the levels seem like they were made with actual building bricks. As well as that, the character movement animations are _really_ simple.
|
||||
|
||||
<img src="/blog/res/small_projects/wobble.gif" width="100%">
|
||||
|
||||
<img src="/blog/res/small_projects/water_wobble.gif" width="100%">
|
||||
|
||||
Both of those aren't even real animations per se, because what they really are is just the player's static texture rotating around a sin wave that is centered on the player's feet. It looks cute, though.
|
||||
|
||||
# The Inner Workings
|
||||
Whenever I write code, I tend to try to overoptimize it a lot. What I mean by that is that I think about systems that I want to implement too intricately sometimes. For instance, if I want to make a tile-based game, I obviously set up some data structures around tiles and how they're going to be ordered and stored on the map. But then, I'll also go and write a bunch of utility methods, conversion functions, figure out a really in-depth coordinate system for dynamic objects, and so on. And, honestly, for projects that aren't too big, all of that isn't really necessary.
|
||||
|
||||
What I did for this game instead is just kind of... let the code take me where it wants to. That may sound a bit ridiculous and performance-intensive, but it honestly works pretty well if you know what you're doing with the framework you're using. A lot of the code in this game is put together somewhat hackily. A lot of hard references to certain items and tile types (like how bombs can only turn grass into dirt and nothing else), a lot of messy utility functions all bunched together into a single class, very little documentation and abstract methods, hub interfaces for things that do similar things, and so on. But that's fine, because this isn't a huge project and I don't plan on adding complicated systems like a modding API or anything like that, so it'd be unnecessary to waste my time on doing something overly fancy.
|
||||
|
||||
For example, the map parsing system is really simple: It consists of an XML file, which stores all the important information about a map like its name and the positions that players spawn in, and a png file.
|
||||
|
||||
<img src="/blog/res/small_projects/map.png" width="100%">
|
||||
|
||||
Each pixel in the file determines which tile will be put at its location. In this instance, black is deep water, blue is shallow water, yellow is sand and green is grass. And the cool thing is that this is really easy to deal with (reading pixels is a simple thing that's present in almost every game framework), because changing something on the map just takes an image editing program, no custom map editor needed.
|
||||
|
||||
# The Gameplay
|
||||
For some of the other games I've worked on, I've always had huge plans to start with. I had this one plan to make a big Animal Crossing-style game with real time progression, tons of NPCs, a lot of complicated gameplay mechanics. I'd worked on a game for over two years that was an open world sandbox, and it was supposed to have a huge story with optional, skippable elements, and... honestly, it's hard to actually make all that happen, at least for me. At some point, I just start looking at it from a different perspective and thinking to myself "Why did I take on such a huge project? This is impossible." and that makes me lose motivation.
|
||||
|
||||
So for Foe Frenzy, I went with a really simple concept that consists of a small amount of clearly definable main points:
|
||||
- Up to four players on a local computer, controlled by keyboard and gamepads
|
||||
- Predefined maps that the players can choose
|
||||
- Item spawners that spawn random items to battle or protect yourself with, where each of the items only lasts for a short time, so you have to keep going back and getting new ones
|
||||
- Kill all the other players to win
|
||||
|
||||
Because I had this clear plan in mind before starting the game, and because it's really not that much to do (I've been working on the game for a month, and all that's left to do is add more maps and more items to battle with), it's been easy to stay on track and stay focused rather than burning out because of responsibility overload.
|
||||
|
||||
# So yea...
|
||||
that's what I've been doing for the last month, and that's why [my other projects](https://minecraft.curseforge.com/projects/natures-aura) have been suffering a little bit. But it's been really fun, and I might even have something to actually release as a real, finished game some time in the near-ish future. It's also been making me feel accomplished, because I've already been able to have my friends test the game out, and they say it's been fun which means that I already accomplished a big part of what I wanted to accomplish with this game.
|
||||
|
||||
Keep updated about the game on [my Discord](https://ellpeck.de/discord) as well as [my Twitter](https://twitter.com/Ellpeck), and I hope you enjoyed reading about the game and my development process so far.
|
||||
|
||||
To finish off, here are some more pictures of the game for your enjoyment.
|
||||
|
||||
<img src="/blog/res/small_projects/cave.png" width="100%">
|
||||
A cave being lit up by torches and lava. This is where a rubber hammer can spawn that you can use to knock the other players into the lava.
|
||||
|
||||
<img src="/blog/res/small_projects/map_select.png" width="100%">
|
||||
The map selection screen, where each player can choose the map that they'd like to play most.
|
||||
|
||||
<img src="/blog/res/small_projects/flame_thrower.gif" width="100%">
|
||||
The favorite item I've added so far: The flamethrower.
|
||||
|
||||
<img src="/blog/res/small_projects/win.gif" width="100%">
|
||||
---
|
||||
layout: blog
|
||||
title: 🗡️ Small Projects
|
||||
description: Why creating a small, unplanned project is sometimes good for you
|
||||
tags: [Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1123651624201871360
|
||||
---
|
||||
|
||||
As it turns out, I struggle a lot with maintaining interest and motivation for working on bigger projects like my [other game](https://rockbottom.ellpeck.de/) or my Minecraft mods. However, an easy fix for that would be to just start less big projects and focus more on smaller ones, like **Foe Frenzy**. Foe Frenzy is a game I've been working on for about a month now.
|
||||
|
||||
<img src="/blog/res/small_projects/contrib.png" width="100%">
|
||||
|
||||
The basic gameplay is finished, as is enough content for my friends to have been testing it for the last week or so and saying that they enjoy it quite a bit, both visually and gameplay-wise. I thought I'd make a blog post about my process of working on it, showing what it's about and what I did this time around to make sure that I don't get burnt out with it.
|
||||
|
||||
<img src="/blog/res/small_projects/overview.png" width="100%">
|
||||
|
||||
_Foe Frenzy is a fast-paced fighting game where you battle up to three of your friends with random, short-lasting items in an attempt to be the last survivor._
|
||||
|
||||
# The Artstyle
|
||||
Not every developer has this problem, but I know a lot do: The inability to make good-looking art. Well, I have this same problem too.
|
||||
A lot of times, I'll find myself getting stuck on making art for my game projects and getting burnt out through trying too hard to force myself to make good-looking art.
|
||||
|
||||
So, this time around, what I did instead of doing that all over again, I just decided to go with _simple art_ instead. For example, as you can see, all the tiles in the world only have 8x8 pixels, and all of them follow a really simple pattern: The top and left side are slightly darker, giving the world a really tiled feel and making the levels seem like they were made with actual building bricks. As well as that, the character movement animations are _really_ simple.
|
||||
|
||||
<img src="/blog/res/small_projects/wobble.gif" width="100%">
|
||||
|
||||
<img src="/blog/res/small_projects/water_wobble.gif" width="100%">
|
||||
|
||||
Both of those aren't even real animations per se, because what they really are is just the player's static texture rotating around a sin wave that is centered on the player's feet. It looks cute, though.
|
||||
|
||||
# The Inner Workings
|
||||
Whenever I write code, I tend to try to overoptimize it a lot. What I mean by that is that I think about systems that I want to implement too intricately sometimes. For instance, if I want to make a tile-based game, I obviously set up some data structures around tiles and how they're going to be ordered and stored on the map. But then, I'll also go and write a bunch of utility methods, conversion functions, figure out a really in-depth coordinate system for dynamic objects, and so on. And, honestly, for projects that aren't too big, all of that isn't really necessary.
|
||||
|
||||
What I did for this game instead is just kind of... let the code take me where it wants to. That may sound a bit ridiculous and performance-intensive, but it honestly works pretty well if you know what you're doing with the framework you're using. A lot of the code in this game is put together somewhat hackily. A lot of hard references to certain items and tile types (like how bombs can only turn grass into dirt and nothing else), a lot of messy utility functions all bunched together into a single class, very little documentation and abstract methods, hub interfaces for things that do similar things, and so on. But that's fine, because this isn't a huge project and I don't plan on adding complicated systems like a modding API or anything like that, so it'd be unnecessary to waste my time on doing something overly fancy.
|
||||
|
||||
For example, the map parsing system is really simple: It consists of an XML file, which stores all the important information about a map like its name and the positions that players spawn in, and a png file.
|
||||
|
||||
<img src="/blog/res/small_projects/map.png" width="100%">
|
||||
|
||||
Each pixel in the file determines which tile will be put at its location. In this instance, black is deep water, blue is shallow water, yellow is sand and green is grass. And the cool thing is that this is really easy to deal with (reading pixels is a simple thing that's present in almost every game framework), because changing something on the map just takes an image editing program, no custom map editor needed.
|
||||
|
||||
# The Gameplay
|
||||
For some of the other games I've worked on, I've always had huge plans to start with. I had this one plan to make a big Animal Crossing-style game with real time progression, tons of NPCs, a lot of complicated gameplay mechanics. I'd worked on a game for over two years that was an open world sandbox, and it was supposed to have a huge story with optional, skippable elements, and... honestly, it's hard to actually make all that happen, at least for me. At some point, I just start looking at it from a different perspective and thinking to myself "Why did I take on such a huge project? This is impossible." and that makes me lose motivation.
|
||||
|
||||
So for Foe Frenzy, I went with a really simple concept that consists of a small amount of clearly definable main points:
|
||||
- Up to four players on a local computer, controlled by keyboard and gamepads
|
||||
- Predefined maps that the players can choose
|
||||
- Item spawners that spawn random items to battle or protect yourself with, where each of the items only lasts for a short time, so you have to keep going back and getting new ones
|
||||
- Kill all the other players to win
|
||||
|
||||
Because I had this clear plan in mind before starting the game, and because it's really not that much to do (I've been working on the game for a month, and all that's left to do is add more maps and more items to battle with), it's been easy to stay on track and stay focused rather than burning out because of responsibility overload.
|
||||
|
||||
# So yea...
|
||||
that's what I've been doing for the last month, and that's why [my other projects](https://minecraft.curseforge.com/projects/natures-aura) have been suffering a little bit. But it's been really fun, and I might even have something to actually release as a real, finished game some time in the near-ish future. It's also been making me feel accomplished, because I've already been able to have my friends test the game out, and they say it's been fun which means that I already accomplished a big part of what I wanted to accomplish with this game.
|
||||
|
||||
Keep updated about the game on [my Discord](https://ellpeck.de/discord) as well as [my Twitter](https://twitter.com/Ellpeck), and I hope you enjoyed reading about the game and my development process so far.
|
||||
|
||||
To finish off, here are some more pictures of the game for your enjoyment.
|
||||
|
||||
<img src="/blog/res/small_projects/cave.png" width="100%">
|
||||
A cave being lit up by torches and lava. This is where a rubber hammer can spawn that you can use to knock the other players into the lava.
|
||||
|
||||
<img src="/blog/res/small_projects/map_select.png" width="100%">
|
||||
The map selection screen, where each player can choose the map that they'd like to play most.
|
||||
|
||||
<img src="/blog/res/small_projects/flame_thrower.gif" width="100%">
|
||||
The favorite item I've added so far: The flamethrower.
|
||||
|
||||
<img src="/blog/res/small_projects/win.gif" width="100%">
|
||||
Killing the last person alive and winning
|
|
@ -1,74 +1,74 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 😔 About Cross-Platform and Motivation
|
||||
summary: How moving from Java to C# taught me how horrible it is to create a cross-platform application with little to no knowledge or documentation
|
||||
tags: [Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1147502654236573697
|
||||
archived: true
|
||||
---
|
||||
|
||||
As originally a java kid, I've never had much trouble with making any of my programs work on Windows, Linux and Mac. With Java, all you have to do is make a jar and then tell people to install Java on their machine. That's it. But oh boy, am I getting hit in the face hard now that I'm making a game with MonoGame and .NET Framework.
|
||||
|
||||
# The story, with all its horrible parts
|
||||
Imagine you're me. Imagine you're just happily making a game and eventually you decide that you want to distribute it to testers.
|
||||
|
||||
## The documentation
|
||||
So you check the documentation of the framework you're using: MonoGame, in my case. It advertises itself as being amazing at cross-platform, so I look around to find a simple tutorial on what to do to get my game working on Mac and Linux.
|
||||
|
||||
Mono is where it's at. Okay. An open source implementation of .NET (or something like that) that works on Linux and Mac. Great! Now I just need to find out how to easily package that with my game, so that people on those operating systems don't have to install it on their own.
|
||||
|
||||
## Mono Kickstart
|
||||
So there's a project on GitHub with a MonoGame fork (meaning they should work together flawlessly!) called Mono Kickstart. It says that you can just add the files to your project, rename a couple of them, change one or two lines in a bash script and then your game will run smoothly on Linux and Mac without having to install Mono.
|
||||
|
||||
Yea, no. Some random issue about `System.Runtime.dll` not being found, no trace of the issue online, no tutorials anywhere, the Kickstart repository doesn't have an Issues tab for some reason. Dead end.
|
||||
|
||||
## mkbundle
|
||||
Searching some more online, I found a tool contained in Mono called mkbundle, that, apparently, you can use to bundle standalone applications for Windows, Linux and Mac by just running a simple command. Seems easy enough.
|
||||
|
||||
Yea, no. Installing Mono on Windows is a huge pain. mkbundle's target downloading doesn't work on Windows, so I have to go into some obscure folders, download some obscure zips, rename them, move them around until it finally works.
|
||||
|
||||
Hah. For some reason, mkbundle now requires me to install Visual Studio. So I install their commandline build tools that, after asking in my Discord, are apparently what mkbundle wants to use for something.
|
||||
|
||||
So then it finally works, and I have a... yea, no. Apparently now, mkbundle can't find `System.Runtime.dll`, just like Mono Kickstart couldn't before. So I search around in some folders and notice that that dll is in a sub-folder instead of the main folder it tries to look for it in, so I tell mkbundle that it's in that subfolder through a long and annoying addition to the command, and now it finally works.
|
||||
|
||||
Yea, just kidding. Now it crashes because it can't find `stdint.h`. It's neither telling me where it's trying to look for it, nor why it even needs it, what it is or really anything of use at all. Dead end.
|
||||
|
||||
## .NET Core
|
||||
After some more looking, I find that .NET Core is basically a better version of .NET Framework (it's actually a lot different, but that doesn't matter in the scope of this post) that actually runs on multiple platforms natively.
|
||||
|
||||
So I go through the process of upgrading my game project from .NET Framework to .NET Core, and everything finally works. I can really easily use my IDE (Rider) to publish packaged builds of the game for Windows, Linux and Mac that don't even need the user to have .NET Core installed.
|
||||
|
||||
Except that it doesn't run on my Laptop for some strange reason. It runs fine on my PC, and it runs fine on my boyfriend's computer and his Linux VM, but my Laptop has some obscure issue about MonoGame not being able to load the shaders it requires. There are also no traces of the issue online, and after some looking around, I realize that MonoGame's .NET Core implementation is, according to the repository, just a hack that also hasn't been updated in over a year. Dead end.
|
||||
|
||||
(Also, I had a weird issue where, with the newest version of MonoGame for .NET Core, my game would randomly stutter, and while the MonoGame Discord was unhelpful and one person was frankly unreasonably rude in my opinion, I found out that it isn't the fault of my code (after plenty of profiling) and that the issue is easily fixed by downgrading to an earlier version. Why? Who even knows at this point.)
|
||||
|
||||
## So I guess I'll just force the user to install Mono themselves then
|
||||
I tested around a bit after going back to .NET Framework and it turns out that installing Mono on Linux isn't actually that bad, and after you installed it, you don't even have to run a special command to get the game to run. All you have to do is go into a terminal and run the game's normal exe, and apparently mono figures itself out without needing to specifically call it. So that's great!
|
||||
|
||||
Except that, on Mac, it seems to be a whole nother story altogether. The one person I asked to try it on Mac installed Mono, but then the system didn't seem to realize that it was actually installed, as the `mono` command didn't work, and just running the game's exe directly also didn't work.
|
||||
|
||||
## Other stuff I tried
|
||||
Because it's so fun, here's a list of other stuff that I tried to use:
|
||||
* Some obscure NuGet package that's supposed to make an easy `msbuild` command to bundle the game. Also didn't work, but at least I submitted an issue to the project's GitHub repository. We'll see what happens, maybe this will be the saving grace.
|
||||
* Some obscure program from three years ago, with outdated packages and outdated dependencies, that was supposed to make it really easy to bundle projects for all operating systems. It had the same `System.Runtime.dll` issue, but because it was so outdated anyway, I didn't even bother investigating why.
|
||||
|
||||
## Conclusion?
|
||||
Honestly, I don't know what to do at this point. After finding out how horrible it is to make anything work cross-platform, I'm genuinely considering just rewriting the entire game using libgdx (which is a game framework for Java), or something.
|
||||
|
||||
There's no real conclusion to this, other than that it took me a whole lot of my time and energy and that it made me buy and eat way too many tubs of Ben & Jerry's ice cream, which is way too expensive, by the way.
|
||||
|
||||
# Also, the Multiplayer debacle
|
||||
As a little side note, I recently added Online Multiplayer to the game in question, using the C# networking library Lidgren.
|
||||
|
||||
Its UPnP implementation doesn't seem to be with my router (or my something else), so I have to manually forward ports as if it were 2003.
|
||||
|
||||
Also, one of the testers has a completely different issue about incomplete packets that I have no idea about, and frankly, my energy to work on anything is so low at this point that I might as well just not care about it.
|
||||
|
||||
# Conclusion
|
||||
If you're thinking about becoming an indie developer, you'll have to deal with this sort of stuff. And honestly, it's going to bring you down. Quite a lot.
|
||||
|
||||
A couple weeks ago, I picked up this project again after taking a long break from it out of lack of motivation, and after picking it back up, I was so happy and energized. I reworked the art to make it look really great, I added more sounds, I hired a music artist, I started implementing online multiplayer, I set a personal roadmap for release on itch.io later this year.
|
||||
|
||||
And then this whole thing happened, and now my motivation is back to zero. It's just extra frustrating to me because I was so excited about finally getting back the motivation that I had previously lost.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 😔 About Cross-Platform and Motivation
|
||||
description: How moving from Java to C# taught me how horrible it is to create a cross-platform application with little to no knowledge or documentation
|
||||
tags: [Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1147502654236573697
|
||||
archived: true
|
||||
---
|
||||
|
||||
As originally a java kid, I've never had much trouble with making any of my programs work on Windows, Linux and Mac. With Java, all you have to do is make a jar and then tell people to install Java on their machine. That's it. But oh boy, am I getting hit in the face hard now that I'm making a game with MonoGame and .NET Framework.
|
||||
|
||||
# The story, with all its horrible parts
|
||||
Imagine you're me. Imagine you're just happily making a game and eventually you decide that you want to distribute it to testers.
|
||||
|
||||
## The documentation
|
||||
So you check the documentation of the framework you're using: MonoGame, in my case. It advertises itself as being amazing at cross-platform, so I look around to find a simple tutorial on what to do to get my game working on Mac and Linux.
|
||||
|
||||
Mono is where it's at. Okay. An open source implementation of .NET (or something like that) that works on Linux and Mac. Great! Now I just need to find out how to easily package that with my game, so that people on those operating systems don't have to install it on their own.
|
||||
|
||||
## Mono Kickstart
|
||||
So there's a project on GitHub with a MonoGame fork (meaning they should work together flawlessly!) called Mono Kickstart. It says that you can just add the files to your project, rename a couple of them, change one or two lines in a bash script and then your game will run smoothly on Linux and Mac without having to install Mono.
|
||||
|
||||
Yea, no. Some random issue about `System.Runtime.dll` not being found, no trace of the issue online, no tutorials anywhere, the Kickstart repository doesn't have an Issues tab for some reason. Dead end.
|
||||
|
||||
## mkbundle
|
||||
Searching some more online, I found a tool contained in Mono called mkbundle, that, apparently, you can use to bundle standalone applications for Windows, Linux and Mac by just running a simple command. Seems easy enough.
|
||||
|
||||
Yea, no. Installing Mono on Windows is a huge pain. mkbundle's target downloading doesn't work on Windows, so I have to go into some obscure folders, download some obscure zips, rename them, move them around until it finally works.
|
||||
|
||||
Hah. For some reason, mkbundle now requires me to install Visual Studio. So I install their commandline build tools that, after asking in my Discord, are apparently what mkbundle wants to use for something.
|
||||
|
||||
So then it finally works, and I have a... yea, no. Apparently now, mkbundle can't find `System.Runtime.dll`, just like Mono Kickstart couldn't before. So I search around in some folders and notice that that dll is in a sub-folder instead of the main folder it tries to look for it in, so I tell mkbundle that it's in that subfolder through a long and annoying addition to the command, and now it finally works.
|
||||
|
||||
Yea, just kidding. Now it crashes because it can't find `stdint.h`. It's neither telling me where it's trying to look for it, nor why it even needs it, what it is or really anything of use at all. Dead end.
|
||||
|
||||
## .NET Core
|
||||
After some more looking, I find that .NET Core is basically a better version of .NET Framework (it's actually a lot different, but that doesn't matter in the scope of this post) that actually runs on multiple platforms natively.
|
||||
|
||||
So I go through the process of upgrading my game project from .NET Framework to .NET Core, and everything finally works. I can really easily use my IDE (Rider) to publish packaged builds of the game for Windows, Linux and Mac that don't even need the user to have .NET Core installed.
|
||||
|
||||
Except that it doesn't run on my Laptop for some strange reason. It runs fine on my PC, and it runs fine on my boyfriend's computer and his Linux VM, but my Laptop has some obscure issue about MonoGame not being able to load the shaders it requires. There are also no traces of the issue online, and after some looking around, I realize that MonoGame's .NET Core implementation is, according to the repository, just a hack that also hasn't been updated in over a year. Dead end.
|
||||
|
||||
(Also, I had a weird issue where, with the newest version of MonoGame for .NET Core, my game would randomly stutter, and while the MonoGame Discord was unhelpful and one person was frankly unreasonably rude in my opinion, I found out that it isn't the fault of my code (after plenty of profiling) and that the issue is easily fixed by downgrading to an earlier version. Why? Who even knows at this point.)
|
||||
|
||||
## So I guess I'll just force the user to install Mono themselves then
|
||||
I tested around a bit after going back to .NET Framework and it turns out that installing Mono on Linux isn't actually that bad, and after you installed it, you don't even have to run a special command to get the game to run. All you have to do is go into a terminal and run the game's normal exe, and apparently mono figures itself out without needing to specifically call it. So that's great!
|
||||
|
||||
Except that, on Mac, it seems to be a whole nother story altogether. The one person I asked to try it on Mac installed Mono, but then the system didn't seem to realize that it was actually installed, as the `mono` command didn't work, and just running the game's exe directly also didn't work.
|
||||
|
||||
## Other stuff I tried
|
||||
Because it's so fun, here's a list of other stuff that I tried to use:
|
||||
* Some obscure NuGet package that's supposed to make an easy `msbuild` command to bundle the game. Also didn't work, but at least I submitted an issue to the project's GitHub repository. We'll see what happens, maybe this will be the saving grace.
|
||||
* Some obscure program from three years ago, with outdated packages and outdated dependencies, that was supposed to make it really easy to bundle projects for all operating systems. It had the same `System.Runtime.dll` issue, but because it was so outdated anyway, I didn't even bother investigating why.
|
||||
|
||||
## Conclusion?
|
||||
Honestly, I don't know what to do at this point. After finding out how horrible it is to make anything work cross-platform, I'm genuinely considering just rewriting the entire game using libgdx (which is a game framework for Java), or something.
|
||||
|
||||
There's no real conclusion to this, other than that it took me a whole lot of my time and energy and that it made me buy and eat way too many tubs of Ben & Jerry's ice cream, which is way too expensive, by the way.
|
||||
|
||||
# Also, the Multiplayer debacle
|
||||
As a little side note, I recently added Online Multiplayer to the game in question, using the C# networking library Lidgren.
|
||||
|
||||
Its UPnP implementation doesn't seem to be with my router (or my something else), so I have to manually forward ports as if it were 2003.
|
||||
|
||||
Also, one of the testers has a completely different issue about incomplete packets that I have no idea about, and frankly, my energy to work on anything is so low at this point that I might as well just not care about it.
|
||||
|
||||
# Conclusion
|
||||
If you're thinking about becoming an indie developer, you'll have to deal with this sort of stuff. And honestly, it's going to bring you down. Quite a lot.
|
||||
|
||||
A couple weeks ago, I picked up this project again after taking a long break from it out of lack of motivation, and after picking it back up, I was so happy and energized. I reworked the art to make it look really great, I added more sounds, I hired a music artist, I started implementing online multiplayer, I set a personal roadmap for release on itch.io later this year.
|
||||
|
||||
And then this whole thing happened, and now my motivation is back to zero. It's just extra frustrating to me because I was so excited about finally getting back the motivation that I had previously lost.
|
||||
|
||||
So yea. Thanks for reading, I guess. <3
|
|
@ -1,54 +1,54 @@
|
|||
---
|
||||
layout: blog
|
||||
title: ⚔️ Big Projects
|
||||
summary: "How a once small project I even created a post about turned into the first game I'm selling: Foe Frenzy"
|
||||
tags: [Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1173247686654517249
|
||||
---
|
||||
|
||||
So I'm releasing a game soon. In December, to be exact. Here's some stuff I did and learned after telling myself that [Foe Frenzy](https://ellpeck.itch.io/FoeFrenzy) would be a [Small Project](https://ellpeck.de/#blog-small_projects) until it suddenly became the first game I'd ever release as a commercial product.
|
||||
|
||||
# In Discord
|
||||
After deciding that I'd only be selling my game on itch.io, I quickly realized that that might not be the best of ideas in the long run, because few people actually know about the platform - despite it being pretty great.
|
||||
|
||||
So I decided to also sell the game on Discord - the Skype-Teamspeak-IRC-hybrid that recently also became a game store. As it turns out, this was *surprisingly* easy: All you have to do is pay $25, go through a really well organized checklist that is provided in Discord's usual jokey writing style and submit. Tada! Your game's on Discord now.
|
||||
By the way, in case you actually want to see what Foe Frenzy's Discord store page currently looks like before release, you should [join my Discord](https://ellpeck.de/discord) and check out its `#ff-store` channel (on Desktop). It looks pretty snazzy!
|
||||
|
||||
## Oh, also:
|
||||
As it turns out, Discord has a game SDK. And Achievement support. And Lobbies, and Multiplayer, and Invites.
|
||||
|
||||
And surprisingly, integrating all of that with Foe Frenzy wasn't necessarily the breeziest breeze ever, as I didn't really have any example implementations or anything of the sort at hand, but it worked out in the end!
|
||||
|
||||
Foe Frenzy will have full compatibility with Discord's Multiplayer features. What does this include, you ask?
|
||||
|
||||
* After hosting a Multiplayer game from Foe Frenzy, you can invite your friends to play with you through the simple click of a button: <blockquote class="twitter-tweet"><p lang="en" dir="ltr">You'll also be able to easily invite people from inside the game! <a href="https://t.co/f3dixbwnxD">pic.twitter.com/f3dixbwnxD</a></p>— Ell (@Ellpeck) <a href="https://twitter.com/Ellpeck/status/1172990814072557573?ref_src=twsrc%5Etfw">September 14, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
* When receiving an invite, you can simply click the Join button which will launch the game and instantly send you into your friend's online lobby: <blockquote class="twitter-tweet"><p lang="en" dir="ltr">SOMETHING IS COMING <a href="https://t.co/ZWVUuRDhD3">pic.twitter.com/ZWVUuRDhD3</a></p>— Ell (@Ellpeck) <a href="https://twitter.com/Ellpeck/status/1172954763803136001?ref_src=twsrc%5Etfw">September 14, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
* From there, you can play online without needing to expose your IP, fiddle around with your router settings or really do anything else.
|
||||
* And have I mentioned... you'll be able to use these features even when buying the game from itch.io, you'll be able to combine Discord and IP-based multiplayer, and you'll even be able to combine online multiplayer and local multiplayer! *So many possibilities!*
|
||||
|
||||
So yea. That's pretty exciting.
|
||||
|
||||
# Music and Trailer
|
||||
So for a rather long time now, I've been watching a YouTuber called [ThinMatrix](https://youtube.com/ThinMatrix) develop his own game, and simultaneously listening to the amazing music for said game, created by the lovely [Jamal Green](https://twitter.com/JamalGreenMusic).
|
||||
|
||||
So after some contemplating (and a lot of anxiety), I decided to send him an email, and quite quickly, he replied and said that, yes indeed, he would love to create the soundtrack for Foe Frenzy. So that's what he's doing now, and it's super awesome.
|
||||
|
||||
In case you haven't seen it yet, here's the announcement trailer for the game which features the awesome trailer theme that he created:
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Z7ZeuVBNuf4" frameborder="0" allow="accelerometer; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
So the moral of that is basically: If you like an artist and want to cooperate with them, don't be scared to message them - the worst that can happen is they say no, and the best that can happen is that they create an awesome soundtrack for you!
|
||||
|
||||
# The whole platform issue
|
||||
If you read all of my blog posts, you'll know about the previous one I made about me trying to figure out how to get a MonoGame project to work well cross-platform without having to upgrade to the not-yet-well-supported .NET Core.
|
||||
|
||||
As it turns out, all I had to do was actually use versions of .NET Framework and netstandard (which is another build target that can be quite confusing to people that aren't used to the whole .NET environment and the weird state it's currently in) that actually, you know, *are compatible with each other*. So after sorting that out, I made [a little tool](https://github.com/Ellpeck/MonoKickstartAutoBundle) that allows you to easily pack any .NET Framework application with Mono without having to even do so much as break a sweat. So that was quite handy.
|
||||
|
||||
# Oh God, what if no one buys my game
|
||||
Obviously, I have a lot of anxiety, as my Twitter feed, the `#feels` channel on my Discord and my therapist make pretty clear.
|
||||
|
||||
So a feeling I have almost *constantly* is the fear that my game won't go well. That no one will care, that no one will buy it, that no one will enjoy it, that it'll be rated horribly, that YouTubers will make fun of it, that... honestly, so many more stupid fears. And obviously, the release hasn't happened yet, and so those fears are still there. But the best advice I can give is to just power through those fears if you also have them, because, as with the e-mail, the worst thing that can happen is that they come true - but the best thing that can happen is that they won't. So, really, the only way it can go is up.
|
||||
|
||||
But also, in case you *do* buy the game once it comes out, and in case you also like it, please tell me. It would mean the world to me. Thanks so much.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: ⚔️ Big Projects
|
||||
description: "How a once small project I even created a post about turned into the first game I'm selling: Foe Frenzy"
|
||||
tags: [Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1173247686654517249
|
||||
---
|
||||
|
||||
So I'm releasing a game soon. In December, to be exact. Here's some stuff I did and learned after telling myself that [Foe Frenzy](https://ellpeck.itch.io/FoeFrenzy) would be a [Small Project](https://ellpeck.de/#blog-small_projects) until it suddenly became the first game I'd ever release as a commercial product.
|
||||
|
||||
# In Discord
|
||||
After deciding that I'd only be selling my game on itch.io, I quickly realized that that might not be the best of ideas in the long run, because few people actually know about the platform - despite it being pretty great.
|
||||
|
||||
So I decided to also sell the game on Discord - the Skype-Teamspeak-IRC-hybrid that recently also became a game store. As it turns out, this was *surprisingly* easy: All you have to do is pay $25, go through a really well organized checklist that is provided in Discord's usual jokey writing style and submit. Tada! Your game's on Discord now.
|
||||
By the way, in case you actually want to see what Foe Frenzy's Discord store page currently looks like before release, you should [join my Discord](https://ellpeck.de/discord) and check out its `#ff-store` channel (on Desktop). It looks pretty snazzy!
|
||||
|
||||
## Oh, also:
|
||||
As it turns out, Discord has a game SDK. And Achievement support. And Lobbies, and Multiplayer, and Invites.
|
||||
|
||||
And surprisingly, integrating all of that with Foe Frenzy wasn't necessarily the breeziest breeze ever, as I didn't really have any example implementations or anything of the sort at hand, but it worked out in the end!
|
||||
|
||||
Foe Frenzy will have full compatibility with Discord's Multiplayer features. What does this include, you ask?
|
||||
|
||||
* After hosting a Multiplayer game from Foe Frenzy, you can invite your friends to play with you through the simple click of a button: <blockquote class="twitter-tweet"><p lang="en" dir="ltr">You'll also be able to easily invite people from inside the game! <a href="https://t.co/f3dixbwnxD">pic.twitter.com/f3dixbwnxD</a></p>— Ell (@Ellpeck) <a href="https://twitter.com/Ellpeck/status/1172990814072557573?ref_src=twsrc%5Etfw">September 14, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
* When receiving an invite, you can simply click the Join button which will launch the game and instantly send you into your friend's online lobby: <blockquote class="twitter-tweet"><p lang="en" dir="ltr">SOMETHING IS COMING <a href="https://t.co/ZWVUuRDhD3">pic.twitter.com/ZWVUuRDhD3</a></p>— Ell (@Ellpeck) <a href="https://twitter.com/Ellpeck/status/1172954763803136001?ref_src=twsrc%5Etfw">September 14, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
||||
* From there, you can play online without needing to expose your IP, fiddle around with your router settings or really do anything else.
|
||||
* And have I mentioned... you'll be able to use these features even when buying the game from itch.io, you'll be able to combine Discord and IP-based multiplayer, and you'll even be able to combine online multiplayer and local multiplayer! *So many possibilities!*
|
||||
|
||||
So yea. That's pretty exciting.
|
||||
|
||||
# Music and Trailer
|
||||
So for a rather long time now, I've been watching a YouTuber called [ThinMatrix](https://youtube.com/ThinMatrix) develop his own game, and simultaneously listening to the amazing music for said game, created by the lovely [Jamal Green](https://twitter.com/JamalGreenMusic).
|
||||
|
||||
So after some contemplating (and a lot of anxiety), I decided to send him an email, and quite quickly, he replied and said that, yes indeed, he would love to create the soundtrack for Foe Frenzy. So that's what he's doing now, and it's super awesome.
|
||||
|
||||
In case you haven't seen it yet, here's the announcement trailer for the game which features the awesome trailer theme that he created:
|
||||
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/Z7ZeuVBNuf4" frameborder="0" allow="accelerometer; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
|
||||
So the moral of that is basically: If you like an artist and want to cooperate with them, don't be scared to message them - the worst that can happen is they say no, and the best that can happen is that they create an awesome soundtrack for you!
|
||||
|
||||
# The whole platform issue
|
||||
If you read all of my blog posts, you'll know about the previous one I made about me trying to figure out how to get a MonoGame project to work well cross-platform without having to upgrade to the not-yet-well-supported .NET Core.
|
||||
|
||||
As it turns out, all I had to do was actually use versions of .NET Framework and netstandard (which is another build target that can be quite confusing to people that aren't used to the whole .NET environment and the weird state it's currently in) that actually, you know, *are compatible with each other*. So after sorting that out, I made [a little tool](https://github.com/Ellpeck/MonoKickstartAutoBundle) that allows you to easily pack any .NET Framework application with Mono without having to even do so much as break a sweat. So that was quite handy.
|
||||
|
||||
# Oh God, what if no one buys my game
|
||||
Obviously, I have a lot of anxiety, as my Twitter feed, the `#feels` channel on my Discord and my therapist make pretty clear.
|
||||
|
||||
So a feeling I have almost *constantly* is the fear that my game won't go well. That no one will care, that no one will buy it, that no one will enjoy it, that it'll be rated horribly, that YouTubers will make fun of it, that... honestly, so many more stupid fears. And obviously, the release hasn't happened yet, and so those fears are still there. But the best advice I can give is to just power through those fears if you also have them, because, as with the e-mail, the worst thing that can happen is that they come true - but the best thing that can happen is that they won't. So, really, the only way it can go is up.
|
||||
|
||||
But also, in case you *do* buy the game once it comes out, and in case you also like it, please tell me. It would mean the world to me. Thanks so much.
|
||||
|
||||
Also, thanks for reading. <3
|
|
@ -1,185 +1,185 @@
|
|||
---
|
||||
layout: blog
|
||||
title: ⬇️ How to make a Rock Bottom mod
|
||||
summary: My adventures back into a game I stopped working on about two years ago and how I start on a mod for it
|
||||
tags: [Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1180092634410487808
|
||||
---
|
||||
|
||||
So it's been a hot minute since I stopped working on my first big game project, [Rock Bottom](https://rockbottomgame.com). Since then, I've changed a lot, but the game hasn't changed that much: For a long time, the project was vacant, until I decided to make it open source. From that point on, a couple of my friends started working on it, adding some new features and fixing some bugs, until it seemingly fell back into vacancy over the last couple of weeks.
|
||||
|
||||
So let's port my recent Minecraft mod, [Nature's Aura](https://www.curseforge.com/minecraft/mc-mods/natures-aura), to Rock Bottom!
|
||||
|
||||
***Note: This is not a tutorial.***
|
||||
|
||||
# Setting up the dev environment
|
||||
Now I *somewhat* remember that, back when I was working on the game, I set up a pretty in-depth modding API as well as an actual Github project to easily allow people to set up a mod themselves.
|
||||
|
||||
*Aha, here it is: [the modding repo](https://github.com/RockBottomGame/Modding).* It even has some nice documentation that I apparently made! Okay, here goes.
|
||||
|
||||
Okay, finding [a build of the game](https://github.com/RockBottomGame/RockBottom/releases) was pretty easy. It even has an in-depth changelog! Good on you, raphy.
|
||||
|
||||
Hm. Okay.
|
||||
So something's already broken.
|
||||
<img src="/blog/res/rock_bottom_mod/1.png" width="100%">
|
||||
|
||||
It looks like here
|
||||
```
|
||||
dependencies {
|
||||
compile group: 'de.ellpeck.rockbottom', name: 'RockBottomAPI', version: '+'
|
||||
}
|
||||
```
|
||||
where it says `+`, it should actally be saying a specific version. So let's replace that with `0.4.6-753` and refresh.
|
||||
|
||||
That didn't seem to fix it either. Huh. Taking a look at [the maven](https://maven.chaosfield.at/de/ellpeck/rockbottom/RockBottomAPI/0.4.6-753/), it seems to be currently down because of `502 bad gateway`. Fun.
|
||||
|
||||
Okay, it's now the next day and it looks like the maven has been fixed, which is nice. So all the compile issues are finally resolved, I put the build into the `/gamedata` folder like explained in the tutorial, I renamed the examplemod to `NaturesAura`, and I can now finally try running the game!
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/2.png" width="100%">
|
||||
Ah! That worked quite well in the end.
|
||||
|
||||
# Actually making something
|
||||
So I feel like the first thing I should add to the game is the golden leaves, because they're also the first thing that you have to create when getting started with the Minecraft version of Nature's Aura.
|
||||
|
||||
So I quickly made a new class that extends `TileBasic`, which I vaguely remember was like an extended, better version of the `Tile` class with some useful helper methods.
|
||||
```java
|
||||
package de.ellpeck.naturesaura.tiles;
|
||||
|
||||
import de.ellpeck.rockbottom.api.tile.TileBasic;
|
||||
import de.ellpeck.rockbottom.api.util.reg.ResourceName;
|
||||
|
||||
public class TileGoldenLeaves extends TileBasic {
|
||||
|
||||
public TileGoldenLeaves(ResourceName name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
My Java is pretty rusty, but I seem to remember all of the naming conventions and, coming from C#, do find myself having trouble with the lowerCamelCase methods (because C# uses UpperCamelCase for method names, conventionally). I quickly made a `Tiles` class that's going to house all the tiles I create and made an instance of the golden leaves tile.
|
||||
|
||||
```java
|
||||
package de.ellpeck.naturesaura.tiles;
|
||||
|
||||
import de.ellpeck.naturesaura.NaturesAura;
|
||||
import de.ellpeck.rockbottom.api.tile.Tile;
|
||||
|
||||
public final class Tiles {
|
||||
|
||||
public static final Tile GOLDEN_LEAVES = new TileGoldenLeaves(NaturesAura.createRes("golden_leaves"));
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
I also created a dummy instance of the Tiles class so that the static variables in it are loaded. If you're not extremely familiar with Java, then this might appear a bit weird for you, but static variables of a class only get instantiated once the class is first used in some way (be it instance creation, method calling, stuff like that), and because I want the golden leaves to be initialized in the `preInit` phase of the game, I just do this:
|
||||
|
||||
```java
|
||||
@Override
|
||||
public void preInit(IGameInstance game, IApiHandler apiHandler, IEventHandler eventHandler) {
|
||||
this.modLogger.info("Starting Nature's Aura for RockBottom");
|
||||
new Tiles();
|
||||
}
|
||||
```
|
||||
|
||||
So far, so good. Let's figure out how to add a texture to the thing.
|
||||
I somewhat remember that I made a horrible json-based asset system (instead of just loading all of the assets in the mod's jar automatically), so I'm going to try to add my tile to the `assets.json` file the example mod provided me with and also add a texture into the actual file system.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/3.png" width="100%">
|
||||
This is the folder structure I decided on. I also created a quick golden version of the game's leaves texture by going to the [asset repository](https://github.com/RockBottomGame/Assets), stealing the leaves texture and recoloring it to be golden-ish.
|
||||
|
||||
Also, I put this in the assets file, but I have no idea if that's actually the right path. We'll find out.
|
||||
```json
|
||||
{
|
||||
"loc.": {
|
||||
"us_english": "/loc/us_english.json"
|
||||
},
|
||||
"tex.": {
|
||||
"tiles.": {
|
||||
"golden_leaves": "/tex/tiles/golden_leaves.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Okay, let's launch and see what happens. So I started the game, opened a lan server, opened the chat, typed `/items` to get a cheat menu, and... it's not showing up. What did I do wrong?
|
||||
|
||||
After some thinking, it turns out that I forgot to actually *register* the tile. So I went back into my `Tiles` class and appended `.register()` to the end of the whole thing, like this:
|
||||
```
|
||||
public static final Tile GOLDEN_LEAVES = new TileGoldenLeaves(NaturesAura.createRes("golden_leaves")).register();
|
||||
```
|
||||
*Crisis averted*.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/4.png" width="100%">
|
||||
Yaaay, it... worked? *Somewhat?*
|
||||
|
||||
You're probably yelling at your screen by now, but yes, I finally noticed it as well: My assets path says `examplemod` instead of `naturesaura`. Easy fix, though.
|
||||
|
||||
While I'm at it though, I can also add a localization entry for the golden leaves. When hovering over it, the console informed me that `Localization with name naturesaura/item.golden_leaves is missing from locale with name us_english!`, so I quickly added it:
|
||||
```json
|
||||
{
|
||||
"naturesaura": {
|
||||
"item.": {
|
||||
"golden_leaves": "Golden Leaves"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Let's try again.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/5.png" width="100%">
|
||||
Ta-da! Success, at last.
|
||||
|
||||
After some investigation, I realized that Rock Bottom's normal leaves can be walked through, so let's see how to make that happen. Typing `@Override` while in the `TileGoldenLeaves` class causes my IDE to list all of the methods I can override. Among them are two that interest me:
|
||||
```java
|
||||
@Override
|
||||
public boolean isFullTile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoundBox getBoundBox(IWorld world, TileState state, int x, int y, TileLayer layer) {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
It seems like this is what I have to do to make the tile walk-through...able. Let's try it out.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/6.png" width="100%">
|
||||
Yay, that seems to have worked. Great.
|
||||
|
||||
# Making an item
|
||||
Now that I have somewhat of a grip of this whole Rock Bottom stuff again, I'm quickly going to make an item. I won't bore you with the details as it's pretty similar to making a tile, but the gist of it is this: I made an `ItemGoldPowder` class that extends `ItemBasic`, and I initialized and registered an instance of that in my newly created `Items` class, of which I created an instance in my mod class's `preInit` method so that it gets initialized at the right time. Also, I did all of the annoying asset mumbo jumbo.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/7.png" width="100%">
|
||||
*Oh, C#, you've ruined me.*
|
||||
|
||||
# Making stuff happen
|
||||
Now, to actually make the gold powder turn normal leaves into golden leaves, I have to write some actual code that isn't just boring boilerplate. When right clicking the golden powder onto a leaves tile, I want that tile to turn into the golden leaves. Eventually, they should then *transition* somehow, but... I'll leave that for later.
|
||||
|
||||
Let's write some code!
|
||||
```java
|
||||
@Override
|
||||
public boolean onInteractWith(IWorld world, int x, int y, TileLayer layer, double mouseX, double mouseY, AbstractEntityPlayer player, ItemInstance instance) {
|
||||
var state = world.getState(layer, x, y);
|
||||
if (state.getTile() != GameContent.TILE_LEAVES)
|
||||
return false;
|
||||
world.setState(layer, x, y, Tiles.GOLDEN_LEAVES.getDefState());
|
||||
player.getInv().remove(player.getSelectedSlot(), 1);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
While writing this code, I quickly remembered that Rock Bottom has a tile state system similar to Minecraft, so I had to work with that. Before I realized, I sat there wondering why `IWorld` doesn't have a `getTile` method anywhere. Anyway, this should check the interacted tile; see if it's leaves; replace the leaves with golden leaves and deduct one from the item being currently held (which is obviously the gold powder, as this is in the `ItemGoldPowder` class. No need for checks there.)
|
||||
|
||||
Let's try it out! ...yea, no. The Java version that gradle uses to compile a Rock Bottom mod isn't new enough yet: You can't use the `var` keyword. Oh, my poor, poor C# soul. So let's swap that `var` out for a `TileState`.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/8.gif" width="100%">
|
||||
Yay, it works! *Except that, in the gif, the mouse position is weirdly offset for some reason. It's correct in person, I promise!*
|
||||
|
||||
# Conclusion
|
||||
So yea, that was the start of my adventure back into Java, back into my old game and back into... well, modding, I guess. I hope you enjoyed reading this post and seeing my process of working out how to do stuff.
|
||||
|
||||
I think it's important to remember that, as a developer (especially an indie developer), you don't have to code everything perfectly or work stuff out correctly the first try. I mean, heck, this is my own game, and I completely forgot how to make a mod for it. But it was fun to figure it out again, and to get back into something I made two years ago.
|
||||
|
||||
Oh, also, if you really want, [here's a build of the mod](https://ellpeck.de/blog/res/rock_bottom_mod/NaturesAuraRockBottom-0.1.jar) that you can try out yourself, as the game is now actually open source and available to everyone! I created this jar with the command `gradlew build`, and all you have to do to run it is [download the game](https://github.com/RockBottomGame/RockBottom/releases), run it once, and then stick the mod jar into its `mods` folder. It really doesn't do that much right now, though, so I don't know why you'd bother.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: ⬇️ How to make a Rock Bottom mod
|
||||
description: My adventures back into a game I stopped working on about two years ago and how I start on a mod for it
|
||||
tags: [Programming]
|
||||
discuss: https://twitter.com/Ellpeck/status/1180092634410487808
|
||||
---
|
||||
|
||||
So it's been a hot minute since I stopped working on my first big game project, [Rock Bottom](https://rockbottomgame.com). Since then, I've changed a lot, but the game hasn't changed that much: For a long time, the project was vacant, until I decided to make it open source. From that point on, a couple of my friends started working on it, adding some new features and fixing some bugs, until it seemingly fell back into vacancy over the last couple of weeks.
|
||||
|
||||
So let's port my recent Minecraft mod, [Nature's Aura](https://www.curseforge.com/minecraft/mc-mods/natures-aura), to Rock Bottom!
|
||||
|
||||
***Note: This is not a tutorial.***
|
||||
|
||||
# Setting up the dev environment
|
||||
Now I *somewhat* remember that, back when I was working on the game, I set up a pretty in-depth modding API as well as an actual Github project to easily allow people to set up a mod themselves.
|
||||
|
||||
*Aha, here it is: [the modding repo](https://github.com/RockBottomGame/Modding).* It even has some nice documentation that I apparently made! Okay, here goes.
|
||||
|
||||
Okay, finding [a build of the game](https://github.com/RockBottomGame/RockBottom/releases) was pretty easy. It even has an in-depth changelog! Good on you, raphy.
|
||||
|
||||
Hm. Okay.
|
||||
So something's already broken.
|
||||
<img src="/blog/res/rock_bottom_mod/1.png" width="100%">
|
||||
|
||||
It looks like here
|
||||
```
|
||||
dependencies {
|
||||
compile group: 'de.ellpeck.rockbottom', name: 'RockBottomAPI', version: '+'
|
||||
}
|
||||
```
|
||||
where it says `+`, it should actally be saying a specific version. So let's replace that with `0.4.6-753` and refresh.
|
||||
|
||||
That didn't seem to fix it either. Huh. Taking a look at [the maven](https://maven.chaosfield.at/de/ellpeck/rockbottom/RockBottomAPI/0.4.6-753/), it seems to be currently down because of `502 bad gateway`. Fun.
|
||||
|
||||
Okay, it's now the next day and it looks like the maven has been fixed, which is nice. So all the compile issues are finally resolved, I put the build into the `/gamedata` folder like explained in the tutorial, I renamed the examplemod to `NaturesAura`, and I can now finally try running the game!
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/2.png" width="100%">
|
||||
Ah! That worked quite well in the end.
|
||||
|
||||
# Actually making something
|
||||
So I feel like the first thing I should add to the game is the golden leaves, because they're also the first thing that you have to create when getting started with the Minecraft version of Nature's Aura.
|
||||
|
||||
So I quickly made a new class that extends `TileBasic`, which I vaguely remember was like an extended, better version of the `Tile` class with some useful helper methods.
|
||||
```java
|
||||
package de.ellpeck.naturesaura.tiles;
|
||||
|
||||
import de.ellpeck.rockbottom.api.tile.TileBasic;
|
||||
import de.ellpeck.rockbottom.api.util.reg.ResourceName;
|
||||
|
||||
public class TileGoldenLeaves extends TileBasic {
|
||||
|
||||
public TileGoldenLeaves(ResourceName name) {
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
My Java is pretty rusty, but I seem to remember all of the naming conventions and, coming from C#, do find myself having trouble with the lowerCamelCase methods (because C# uses UpperCamelCase for method names, conventionally). I quickly made a `Tiles` class that's going to house all the tiles I create and made an instance of the golden leaves tile.
|
||||
|
||||
```java
|
||||
package de.ellpeck.naturesaura.tiles;
|
||||
|
||||
import de.ellpeck.naturesaura.NaturesAura;
|
||||
import de.ellpeck.rockbottom.api.tile.Tile;
|
||||
|
||||
public final class Tiles {
|
||||
|
||||
public static final Tile GOLDEN_LEAVES = new TileGoldenLeaves(NaturesAura.createRes("golden_leaves"));
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
I also created a dummy instance of the Tiles class so that the static variables in it are loaded. If you're not extremely familiar with Java, then this might appear a bit weird for you, but static variables of a class only get instantiated once the class is first used in some way (be it instance creation, method calling, stuff like that), and because I want the golden leaves to be initialized in the `preInit` phase of the game, I just do this:
|
||||
|
||||
```java
|
||||
@Override
|
||||
public void preInit(IGameInstance game, IApiHandler apiHandler, IEventHandler eventHandler) {
|
||||
this.modLogger.info("Starting Nature's Aura for RockBottom");
|
||||
new Tiles();
|
||||
}
|
||||
```
|
||||
|
||||
So far, so good. Let's figure out how to add a texture to the thing.
|
||||
I somewhat remember that I made a horrible json-based asset system (instead of just loading all of the assets in the mod's jar automatically), so I'm going to try to add my tile to the `assets.json` file the example mod provided me with and also add a texture into the actual file system.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/3.png" width="100%">
|
||||
This is the folder structure I decided on. I also created a quick golden version of the game's leaves texture by going to the [asset repository](https://github.com/RockBottomGame/Assets), stealing the leaves texture and recoloring it to be golden-ish.
|
||||
|
||||
Also, I put this in the assets file, but I have no idea if that's actually the right path. We'll find out.
|
||||
```json
|
||||
{
|
||||
"loc.": {
|
||||
"us_english": "/loc/us_english.json"
|
||||
},
|
||||
"tex.": {
|
||||
"tiles.": {
|
||||
"golden_leaves": "/tex/tiles/golden_leaves.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Okay, let's launch and see what happens. So I started the game, opened a lan server, opened the chat, typed `/items` to get a cheat menu, and... it's not showing up. What did I do wrong?
|
||||
|
||||
After some thinking, it turns out that I forgot to actually *register* the tile. So I went back into my `Tiles` class and appended `.register()` to the end of the whole thing, like this:
|
||||
```
|
||||
public static final Tile GOLDEN_LEAVES = new TileGoldenLeaves(NaturesAura.createRes("golden_leaves")).register();
|
||||
```
|
||||
*Crisis averted*.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/4.png" width="100%">
|
||||
Yaaay, it... worked? *Somewhat?*
|
||||
|
||||
You're probably yelling at your screen by now, but yes, I finally noticed it as well: My assets path says `examplemod` instead of `naturesaura`. Easy fix, though.
|
||||
|
||||
While I'm at it though, I can also add a localization entry for the golden leaves. When hovering over it, the console informed me that `Localization with name naturesaura/item.golden_leaves is missing from locale with name us_english!`, so I quickly added it:
|
||||
```json
|
||||
{
|
||||
"naturesaura": {
|
||||
"item.": {
|
||||
"golden_leaves": "Golden Leaves"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Let's try again.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/5.png" width="100%">
|
||||
Ta-da! Success, at last.
|
||||
|
||||
After some investigation, I realized that Rock Bottom's normal leaves can be walked through, so let's see how to make that happen. Typing `@Override` while in the `TileGoldenLeaves` class causes my IDE to list all of the methods I can override. Among them are two that interest me:
|
||||
```java
|
||||
@Override
|
||||
public boolean isFullTile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoundBox getBoundBox(IWorld world, TileState state, int x, int y, TileLayer layer) {
|
||||
return null;
|
||||
}
|
||||
```
|
||||
It seems like this is what I have to do to make the tile walk-through...able. Let's try it out.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/6.png" width="100%">
|
||||
Yay, that seems to have worked. Great.
|
||||
|
||||
# Making an item
|
||||
Now that I have somewhat of a grip of this whole Rock Bottom stuff again, I'm quickly going to make an item. I won't bore you with the details as it's pretty similar to making a tile, but the gist of it is this: I made an `ItemGoldPowder` class that extends `ItemBasic`, and I initialized and registered an instance of that in my newly created `Items` class, of which I created an instance in my mod class's `preInit` method so that it gets initialized at the right time. Also, I did all of the annoying asset mumbo jumbo.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/7.png" width="100%">
|
||||
*Oh, C#, you've ruined me.*
|
||||
|
||||
# Making stuff happen
|
||||
Now, to actually make the gold powder turn normal leaves into golden leaves, I have to write some actual code that isn't just boring boilerplate. When right clicking the golden powder onto a leaves tile, I want that tile to turn into the golden leaves. Eventually, they should then *transition* somehow, but... I'll leave that for later.
|
||||
|
||||
Let's write some code!
|
||||
```java
|
||||
@Override
|
||||
public boolean onInteractWith(IWorld world, int x, int y, TileLayer layer, double mouseX, double mouseY, AbstractEntityPlayer player, ItemInstance instance) {
|
||||
var state = world.getState(layer, x, y);
|
||||
if (state.getTile() != GameContent.TILE_LEAVES)
|
||||
return false;
|
||||
world.setState(layer, x, y, Tiles.GOLDEN_LEAVES.getDefState());
|
||||
player.getInv().remove(player.getSelectedSlot(), 1);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
While writing this code, I quickly remembered that Rock Bottom has a tile state system similar to Minecraft, so I had to work with that. Before I realized, I sat there wondering why `IWorld` doesn't have a `getTile` method anywhere. Anyway, this should check the interacted tile; see if it's leaves; replace the leaves with golden leaves and deduct one from the item being currently held (which is obviously the gold powder, as this is in the `ItemGoldPowder` class. No need for checks there.)
|
||||
|
||||
Let's try it out! ...yea, no. The Java version that gradle uses to compile a Rock Bottom mod isn't new enough yet: You can't use the `var` keyword. Oh, my poor, poor C# soul. So let's swap that `var` out for a `TileState`.
|
||||
|
||||
<img src="/blog/res/rock_bottom_mod/8.gif" width="100%">
|
||||
Yay, it works! *Except that, in the gif, the mouse position is weirdly offset for some reason. It's correct in person, I promise!*
|
||||
|
||||
# Conclusion
|
||||
So yea, that was the start of my adventure back into Java, back into my old game and back into... well, modding, I guess. I hope you enjoyed reading this post and seeing my process of working out how to do stuff.
|
||||
|
||||
I think it's important to remember that, as a developer (especially an indie developer), you don't have to code everything perfectly or work stuff out correctly the first try. I mean, heck, this is my own game, and I completely forgot how to make a mod for it. But it was fun to figure it out again, and to get back into something I made two years ago.
|
||||
|
||||
Oh, also, if you really want, [here's a build of the mod](https://ellpeck.de/blog/res/rock_bottom_mod/NaturesAuraRockBottom-0.1.jar) that you can try out yourself, as the game is now actually open source and available to everyone! I created this jar with the command `gradlew build`, and all you have to do to run it is [download the game](https://github.com/RockBottomGame/RockBottom/releases), run it once, and then stick the mod jar into its `mods` folder. It really doesn't do that much right now, though, so I don't know why you'd bother.
|
||||
|
||||
As always, thanks for reading!
|
|
@ -1,105 +1,105 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 1: Hello World"
|
||||
summary: The first part of my post series for programming beginners where I explain how to write code in Java.
|
||||
tags: [Java Tutorials, Featured]
|
||||
discuss: https://twitter.com/Ellpeck/status/1182080078827737088
|
||||
---
|
||||
|
||||
So you want to learn to code. In my opinion, a good language for beginners is Java, because it's a rather easy to understand language, and it's cross-platform, meaning it can run on any operating system without the need for the programmer (you!) to change anything based on the platform. Also, Java is object-oriented (more on that later), meaning it's pretty good for writing any sort of simple or complex program.[^1]
|
||||
|
||||
So let's start!
|
||||
|
||||
# Setting it up
|
||||
To actually be able to compile[^2] any Java code, you first need to download the [Java Development Kit](https://jdk.java.net/), or JDK for short. If you're a Linux or Mac user, you can just follow [their installation tutorial](https://openjdk.java.net/install/), and if you're on Windows, you can follow [this tutorial from Stack Overflow](https://stackoverflow.com/a/52531093). To check if the installation worked, you can just type `java -version` into a command prompt (which you can open on Windows by just typing `cmd` into your search).
|
||||
|
||||
Some people might disagree with me on this, but I recommend using an Integrated Development Environment (IDE) for development *especially* when you're just starting out. An IDE is a program that helps you with coding by suggesting changes, notifying you of errors in your code and also allows you to easily run and debug your application. My personal suggestion would be to install [IntelliJ IDEA](https://www.jetbrains.com/idea/), but you could also use other IDEs like [Eclipse](https://www.eclipse.org/downloads/).
|
||||
|
||||
The next thing you'll have to do is create a new project inside your IDE. For IntelliJ, all you have to do is click `New Project`, select `Java`, click `Next` twice and then type your project's name. I'm going to go with `JavaTutorial` for mine.
|
||||
|
||||
# Hello World
|
||||
Once that's done, we can finally start programming. At first, you'll find that a lot of the stuff we're doing isn't explained directly, but I'll come back to some of the things I'm showing you now at a later point. Things like classes, methods and parameters probably won't make sense to you yet, but using them is required for even the most basic of running programs.
|
||||
|
||||
The first thing we want to do is create a simple program that outputs something back to the user inside of the program's console. To start, simply right click your `src` folder and select `New` and `Java Class` and give it a name like `Main`. I'll show you the code for it first and then give you a quick rundown of the important parts you need to know about it for now.
|
||||
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello Tutorial World!");
|
||||
}
|
||||
}
|
||||
```
|
||||
That's it! If you now run your program (for IntelliJ, there should be a small green arrow to the left that you can click on), it'll print out the message to the console and then stop the program.
|
||||
|
||||
A lot of the code you see above doesn't *really* matter to you right now. The important stuff is this:
|
||||
- Each instruction, each thing that the program should do, ends with a semicolon `;` and usually a new line, though that is optional.
|
||||
- Any instruction you write between the inner curly braces `{}` will be executed in order of how it's written.
|
||||
- `System.out.println("<enter anything here>")` is an instruction that causes a line of text to be written to the console.
|
||||
|
||||
As a little exercise, you can make your program output another line of text:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello Tutorial World!");
|
||||
System.out.println("This is another line of text!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Variables
|
||||
Now the first thing you'll probably want to do is learn what variables are and how to use them. A variable, simply put, is any kind of value (a number, a string of text etc.) that can be changed and that has a name. In Java, each variable also has to have a fixed type: While a variable's *value* can be changed (say, from `some text` to `some other text`), its *type* cannot be changed (so a variable representing text cannot be changed into a variable representing a number). Variables are created as follows:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello Tutorial World!");
|
||||
System.out.println("This is another line of text!");
|
||||
|
||||
String someText;
|
||||
int someNumber;
|
||||
|
||||
someText = "Some Text";
|
||||
someNumber = 10;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see from line 6 and 7, to declare a variable, you need to put the variable's type first (`String` meaning text, `int` meaning an integer; a number without a decimal point), followed by the variable's name, which you can choose yourself.
|
||||
|
||||
For now, these variables don't have a value assigned to them yet. That's done in line 9 and 10. To assign a value to a variable, you first put the variable's name, followed by an equals sign `=`, followed by your desired value. For numbers, you can simply put them down, but text has to be wrapped in quotes `""` (which is also why the text in lines 3 and 4 is wrapped in quotes).
|
||||
|
||||
To actually do something with the variables, let's have them be printed out to the console. *I've omitted the rest of the code here because it's getting quite long, but I'm just adding the following lines inside the inner braces `{}` below the already written code.*
|
||||
```java
|
||||
System.out.println(someText);
|
||||
System.out.println(someNumber);
|
||||
```
|
||||
As you can see, to print a variable's value to the console, all you have to do is put its name where you would usually put a piece of text directly.
|
||||
|
||||
# Variable Manipulation
|
||||
Obviously, this isn't really that exciting yet: Our program isn't really doing anything so far. Let's manipulate our variables. I've added the following code:
|
||||
```java
|
||||
someNumber = someNumber + 5;
|
||||
System.out.println(someNumber);
|
||||
```
|
||||
As you can see, you can use a plus sign `+` (as well as other mathematical operators) to do math with numbers. The first statement changes `someNumber`'s value to a new value: `someNumber + 5`. Running the program will show you that the result is pretty obvious: 15 is printed, because 10 + 5 = 15.
|
||||
|
||||
The same kind of manipulation can be done with text, which is especially useful for printing variables to the console. The plus sign `+` chains two strings of text together.
|
||||
```java
|
||||
String chainedText = "The resulting value is " + someNumber;
|
||||
System.out.println(chainedText);
|
||||
```
|
||||
Here, a new variable is created (`String chainedText`) and its value is set (`=`) to the shown string plus the value of the `someNumber` variable. When added to the rest of the code, running this code should display `The resulting value is 15`.
|
||||
|
||||
# Conclusion
|
||||
Now obviously, this is just the beginning of what you can learn and do with Java. I feel like this is a good point to finish the first part of this tutorial. I know it's probably not super interesting yet, but bear with me for a little while and you'll pretty quickly be able to do some pretty cool stuff.
|
||||
|
||||
Before you click away, I'd like to ask you some questions that you can answer by clicking on the discussion link below this post:
|
||||
- Could you follow this tutorial?
|
||||
- What do you think about the pacing? Is it too fast or too slow, are there too many examples or too few?
|
||||
- Do you want me to actually continue this tutorial series?
|
||||
|
||||
Anyway, thanks a lot for reading and happy coding! <3
|
||||
|
||||
***
|
||||
|
||||
[^1]: Also, it's what Minecraft mods are written in, which is probably the reason most of you are here.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 1: Hello World"
|
||||
description: The first part of my post series for programming beginners where I explain how to write code in Java.
|
||||
tags: [Java Tutorials, Featured]
|
||||
discuss: https://twitter.com/Ellpeck/status/1182080078827737088
|
||||
---
|
||||
|
||||
So you want to learn to code. In my opinion, a good language for beginners is Java, because it's a rather easy to understand language, and it's cross-platform, meaning it can run on any operating system without the need for the programmer (you!) to change anything based on the platform. Also, Java is object-oriented (more on that later), meaning it's pretty good for writing any sort of simple or complex program.[^1]
|
||||
|
||||
So let's start!
|
||||
|
||||
# Setting it up
|
||||
To actually be able to compile[^2] any Java code, you first need to download the [Java Development Kit](https://jdk.java.net/), or JDK for short. If you're a Linux or Mac user, you can just follow [their installation tutorial](https://openjdk.java.net/install/), and if you're on Windows, you can follow [this tutorial from Stack Overflow](https://stackoverflow.com/a/52531093). To check if the installation worked, you can just type `java -version` into a command prompt (which you can open on Windows by just typing `cmd` into your search).
|
||||
|
||||
Some people might disagree with me on this, but I recommend using an Integrated Development Environment (IDE) for development *especially* when you're just starting out. An IDE is a program that helps you with coding by suggesting changes, notifying you of errors in your code and also allows you to easily run and debug your application. My personal suggestion would be to install [IntelliJ IDEA](https://www.jetbrains.com/idea/), but you could also use other IDEs like [Eclipse](https://www.eclipse.org/downloads/).
|
||||
|
||||
The next thing you'll have to do is create a new project inside your IDE. For IntelliJ, all you have to do is click `New Project`, select `Java`, click `Next` twice and then type your project's name. I'm going to go with `JavaTutorial` for mine.
|
||||
|
||||
# Hello World
|
||||
Once that's done, we can finally start programming. At first, you'll find that a lot of the stuff we're doing isn't explained directly, but I'll come back to some of the things I'm showing you now at a later point. Things like classes, methods and parameters probably won't make sense to you yet, but using them is required for even the most basic of running programs.
|
||||
|
||||
The first thing we want to do is create a simple program that outputs something back to the user inside of the program's console. To start, simply right click your `src` folder and select `New` and `Java Class` and give it a name like `Main`. I'll show you the code for it first and then give you a quick rundown of the important parts you need to know about it for now.
|
||||
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello Tutorial World!");
|
||||
}
|
||||
}
|
||||
```
|
||||
That's it! If you now run your program (for IntelliJ, there should be a small green arrow to the left that you can click on), it'll print out the message to the console and then stop the program.
|
||||
|
||||
A lot of the code you see above doesn't *really* matter to you right now. The important stuff is this:
|
||||
- Each instruction, each thing that the program should do, ends with a semicolon `;` and usually a new line, though that is optional.
|
||||
- Any instruction you write between the inner curly braces `{}` will be executed in order of how it's written.
|
||||
- `System.out.println("<enter anything here>")` is an instruction that causes a line of text to be written to the console.
|
||||
|
||||
As a little exercise, you can make your program output another line of text:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello Tutorial World!");
|
||||
System.out.println("This is another line of text!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Variables
|
||||
Now the first thing you'll probably want to do is learn what variables are and how to use them. A variable, simply put, is any kind of value (a number, a string of text etc.) that can be changed and that has a name. In Java, each variable also has to have a fixed type: While a variable's *value* can be changed (say, from `some text` to `some other text`), its *type* cannot be changed (so a variable representing text cannot be changed into a variable representing a number). Variables are created as follows:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello Tutorial World!");
|
||||
System.out.println("This is another line of text!");
|
||||
|
||||
String someText;
|
||||
int someNumber;
|
||||
|
||||
someText = "Some Text";
|
||||
someNumber = 10;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see from line 6 and 7, to declare a variable, you need to put the variable's type first (`String` meaning text, `int` meaning an integer; a number without a decimal point), followed by the variable's name, which you can choose yourself.
|
||||
|
||||
For now, these variables don't have a value assigned to them yet. That's done in line 9 and 10. To assign a value to a variable, you first put the variable's name, followed by an equals sign `=`, followed by your desired value. For numbers, you can simply put them down, but text has to be wrapped in quotes `""` (which is also why the text in lines 3 and 4 is wrapped in quotes).
|
||||
|
||||
To actually do something with the variables, let's have them be printed out to the console. *I've omitted the rest of the code here because it's getting quite long, but I'm just adding the following lines inside the inner braces `{}` below the already written code.*
|
||||
```java
|
||||
System.out.println(someText);
|
||||
System.out.println(someNumber);
|
||||
```
|
||||
As you can see, to print a variable's value to the console, all you have to do is put its name where you would usually put a piece of text directly.
|
||||
|
||||
# Variable Manipulation
|
||||
Obviously, this isn't really that exciting yet: Our program isn't really doing anything so far. Let's manipulate our variables. I've added the following code:
|
||||
```java
|
||||
someNumber = someNumber + 5;
|
||||
System.out.println(someNumber);
|
||||
```
|
||||
As you can see, you can use a plus sign `+` (as well as other mathematical operators) to do math with numbers. The first statement changes `someNumber`'s value to a new value: `someNumber + 5`. Running the program will show you that the result is pretty obvious: 15 is printed, because 10 + 5 = 15.
|
||||
|
||||
The same kind of manipulation can be done with text, which is especially useful for printing variables to the console. The plus sign `+` chains two strings of text together.
|
||||
```java
|
||||
String chainedText = "The resulting value is " + someNumber;
|
||||
System.out.println(chainedText);
|
||||
```
|
||||
Here, a new variable is created (`String chainedText`) and its value is set (`=`) to the shown string plus the value of the `someNumber` variable. When added to the rest of the code, running this code should display `The resulting value is 15`.
|
||||
|
||||
# Conclusion
|
||||
Now obviously, this is just the beginning of what you can learn and do with Java. I feel like this is a good point to finish the first part of this tutorial. I know it's probably not super interesting yet, but bear with me for a little while and you'll pretty quickly be able to do some pretty cool stuff.
|
||||
|
||||
Before you click away, I'd like to ask you some questions that you can answer by clicking on the discussion link below this post:
|
||||
- Could you follow this tutorial?
|
||||
- What do you think about the pacing? Is it too fast or too slow, are there too many examples or too few?
|
||||
- Do you want me to actually continue this tutorial series?
|
||||
|
||||
Anyway, thanks a lot for reading and happy coding! <3
|
||||
|
||||
***
|
||||
|
||||
[^1]: Also, it's what Minecraft mods are written in, which is probably the reason most of you are here.
|
||||
|
||||
[^2]: Compiling is what occurs when code written by you is converted into something that the computer can actually understand. More on that later, probably.
|
|
@ -1,171 +1,171 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 2: Intro to Conditions and Loops"
|
||||
summary: The second part of my post series for programming beginners. This one is all about conditions and loops.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1182354544707198976
|
||||
---
|
||||
|
||||
If you're reading this, then I assume you have already read the first part of this tutorial series, in which we covered setting up a program, making it print "Hello World" to the console, as well as how to declare and set the values of variables.
|
||||
|
||||
Today, we'll be talking about conditions and loops.[^1] As with the last tutorial, I'll be writing most of the code snippets first and then explaining what exactly they mean and do right after.
|
||||
|
||||
# The `if` condition
|
||||
Let's say you want to create a program that checks if a given number `i` is greater than or equal to 27. Well, you do it like this:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// This is where the code from the first tutorial would be
|
||||
// if I hadn't deleted it for visual clarity
|
||||
|
||||
// Also, side note: You can use "//" to create comments:
|
||||
// lines that aren't interpreted as code.
|
||||
|
||||
int i = 15;
|
||||
if (i >= 27) {
|
||||
System.out.println("i is greater than or equal to 27!");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
So what we see here is called the `if` condition. It's structured as follows: You write the word `if`, followed by *the condition*, which is wrapped in parentheses `()`. You can then open curly braces `{}`, and any instructions that are written between them will only be executed if your supplied condition holds true.
|
||||
|
||||
The condition can be any statement that can either be `true` (correct) or `false` (incorrect). In this case, we're comparing two numbers with each other; there are several other ways to compare two numbers: `>`, `<`, `>=`, `<=`, `!=` and `==`, where the last two mean "not equal" and "exactly equal".[^2]
|
||||
|
||||
An important thing to note at this point is that this behavior is *different* with `String` variables.[^3] Comparing if two strings are equal by using `==` will not result in the behavior you might expect. Instead, you should compare two strings using `equals()` as follows:
|
||||
```java
|
||||
String s1 = "This is some text";
|
||||
String s2 = "This is also some text";
|
||||
if (s1.equals(s2)) {
|
||||
System.out.println("s1 and s2 are equal!");
|
||||
}
|
||||
```
|
||||
|
||||
## The `boolean` type
|
||||
A condition like this (which can either be `true` or `false`) can also be stored in a `boolean` variable[^4] whose state can then be checked using a similar `if` statement:
|
||||
```java
|
||||
int i = 15;
|
||||
boolean i27 = i >= 27;
|
||||
if (i27) {
|
||||
System.out.println("i is greater than or equal to 27!");
|
||||
}
|
||||
```
|
||||
The above code has the same effect as the code we looked at before. The cool thing about this method is that you can easily check if a condition *doesn't* hold true by simply adding an exclamation point `!` in front of any boolean variable:
|
||||
```java
|
||||
if (!i27) {
|
||||
System.out.println("i is NOT greater than or equal to 27!");
|
||||
}
|
||||
|
||||
// As you can see, this is especially useful when comparing strings
|
||||
String s1 = "This is some text";
|
||||
String s2 = "This is also some text";
|
||||
if (!s1.equals(s2)) {
|
||||
System.out.println("s1 and s2 are NOT equal!");
|
||||
}
|
||||
```
|
||||
|
||||
Additionally, two boolean variables (or simply two conditions) can be chained together in two ways:
|
||||
```java
|
||||
int i = 15;
|
||||
if (i == 12 || i == 13) {
|
||||
System.out.println("i is either 12 or 13!");
|
||||
}
|
||||
if (i >= 10 && i < 20) {
|
||||
System.out.println("i is somewhere between 10 and 20");
|
||||
}
|
||||
```
|
||||
As you can see in lines 2 to 4, two pipes `||` represent the `OR` operator: A combined condition using it holds true if the left side is true, or the right side is true, or both sides are true.
|
||||
As you can see in lines 5 to 7, two ampersands `&&` represent the `AND` operator: A combined condition using it holds true if *both* sides are also true.
|
||||
|
||||
You can also wrap your checks in parentheses `()` to create a more complex condition, similarly to how you would use them in a mathematical expression:
|
||||
```java
|
||||
int j = 10;
|
||||
int k = 15;
|
||||
boolean combination = (j == 12 && k == 13) || (j == 10 && k == 25);
|
||||
System.out.println(combination);
|
||||
```
|
||||
The above code will cause `true` to be printed if `j` equals 12 and `k` equals 13 *or* if `j` equals 10 and `k` equals 25. Otherwise, `false` will be printed.
|
||||
|
||||
## `else`
|
||||
If you want something *else* to happen if a certain condition doesn't hold true, then you can do something like the following:
|
||||
```java
|
||||
int i = 15;
|
||||
if (i >= 27) {
|
||||
System.out.println("i is greater than or equal to 27!");
|
||||
} else {
|
||||
System.out.println("i is less than 27 :(");
|
||||
}
|
||||
```
|
||||
As you can see, writing `else` after any `if` statement causes the code contained in the following curly braces `{}` to only be executed if the `if` statement's condition *isn't* true.
|
||||
|
||||
Optionally, you can also combine the `else` with another `if` statement to check for a different condition. You can do this as many times as you want:
|
||||
```java
|
||||
int i = 15;
|
||||
if (i >= 27) {
|
||||
System.out.println("i is greater than or equal to 27!");
|
||||
} else if (i <= 10) {
|
||||
System.out.println("i is less than 27, but also less than or equal to 10");
|
||||
} else {
|
||||
System.out.println("i is somewhere between 11 and 26");
|
||||
}
|
||||
```
|
||||
|
||||
# The `for` loop
|
||||
The `if` condition is already pretty powerful, because you can execute different code based on different situations. Another useful thing is the `for` loop. How it's written and what it does can be a bit complicated to understand at first, but I'll try to break the following example down for you:
|
||||
```java
|
||||
for (int index = 0; index < 3; index = index + 1) {
|
||||
System.out.println("The current index is " + index);
|
||||
}
|
||||
```
|
||||
This specific `for` loop causes the following to be printed to the console:
|
||||
```
|
||||
The current index is 0
|
||||
The current index is 1
|
||||
The current index is 2
|
||||
```
|
||||
As you might be able to tell from that, a `for` loop causes any number of instructions in it to be executed a certain amount of times.
|
||||
|
||||
Its structure is pretty similar to the `if` statement's: First, you write the word `for`, followed by some loop instructions inside parentheses `()`, and then you open curly braces `{}` which contain the instructions that should be executed multiple times. The loop instructions contain three parts, which are separated by semicolons `;`:
|
||||
- `int index = 0;` is the declaration of the *loop variable*: This is the instruction that will be executed *before* the loop starts running.
|
||||
- `index < 3;` is the *loop's condition*: Before every time the loop's content is run, a check is done to make sure that this condition is still true. If it's not true anymore, the loop stops running.
|
||||
- `index = index + 1` is the instruction that is executed *after* every time the loop's content has finished running.
|
||||
|
||||
So in the case of our loop, the following things happen:
|
||||
- The `index` variable is declared and set to 0.
|
||||
- `index < 3` is checked, which is obviously true.
|
||||
- The loop's content is run, which causes the print to the console.
|
||||
- `index = index + 1` is executed, which sets `index` to 1.
|
||||
- `index < 3` is checked, which is still true.
|
||||
- The loop's content is run again, and so on.
|
||||
|
||||
## `break`
|
||||
If you want to exit a `for` loop before its condition turns to `false`, you can use the `break;` statement as follows:
|
||||
```java
|
||||
for (int index = 0; index < 10000; index = index + 1) {
|
||||
System.out.println("The current index is " + index);
|
||||
|
||||
if (index >= 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
This loop has the same effect as the one we looked at before. Despite the loop condition specifying that it should repeat 10000 times, it is only repeated three times, because the condition on line 4 is evaluated every time and the loop is forced to stop running once it is true.
|
||||
|
||||
# Conclusion
|
||||
In this tutorial, you (hopefully) learned what the `if` and `for` statements are and how to use them. By now, you should be able to write some more complicated code. As a little exercise, you can try to solve the following problem using the things you learned in the last two tutorials:
|
||||
|
||||
> Given a variable `i` and another variable `exp`, calculate if the result of `i`<sup>`exp`</sup> (`i` to the power of `exp`) is less than or equal to the value of another variable `j` (and print the result to the console accordingly).
|
||||
|
||||
If you're stuck, you can check out my solution [here](https://gist.github.com/Ellpeck/999bafe352f84d5e1f09750e026d5bbf).
|
||||
|
||||
Thanks for reading this tutorial and I hope it helped you out! If you have any feedback or questions about it, you can click the discussion link below and ask me on Twitter, or join my Discord server using the widget on the main page. Happy coding!
|
||||
|
||||
***
|
||||
|
||||
[^1]: I'm covering this topic *before* I cover what exactly classes and methods are. I think that conditions and loops take importance here, because they're used broadly in every language as well as most programs, whereas object orientation is a feature specific to some languages, as well as specific to more "complex" programs. It's also somewhat complicated, and I want to explain it right, because when I learned Java, I didn't even remotely understand it correctly at first.
|
||||
|
||||
[^2]: Note that, when *comparing* two numbers, two equals signs `==` are used. This is different from *assigning a value* to a variable, which only uses one equals sign `=`.
|
||||
|
||||
[^3]: Why exactly this is the case will be discussed later when we get into object orientation. The different behavior mentioned here is the case for any variable types which aren't so-called *native types*. Any variable whose type starts with an uppercase letter is not a native type, because it derives from a *class*.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 2: Intro to Conditions and Loops"
|
||||
description: The second part of my post series for programming beginners. This one is all about conditions and loops.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1182354544707198976
|
||||
---
|
||||
|
||||
If you're reading this, then I assume you have already read the first part of this tutorial series, in which we covered setting up a program, making it print "Hello World" to the console, as well as how to declare and set the values of variables.
|
||||
|
||||
Today, we'll be talking about conditions and loops.[^1] As with the last tutorial, I'll be writing most of the code snippets first and then explaining what exactly they mean and do right after.
|
||||
|
||||
# The `if` condition
|
||||
Let's say you want to create a program that checks if a given number `i` is greater than or equal to 27. Well, you do it like this:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// This is where the code from the first tutorial would be
|
||||
// if I hadn't deleted it for visual clarity
|
||||
|
||||
// Also, side note: You can use "//" to create comments:
|
||||
// lines that aren't interpreted as code.
|
||||
|
||||
int i = 15;
|
||||
if (i >= 27) {
|
||||
System.out.println("i is greater than or equal to 27!");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
So what we see here is called the `if` condition. It's structured as follows: You write the word `if`, followed by *the condition*, which is wrapped in parentheses `()`. You can then open curly braces `{}`, and any instructions that are written between them will only be executed if your supplied condition holds true.
|
||||
|
||||
The condition can be any statement that can either be `true` (correct) or `false` (incorrect). In this case, we're comparing two numbers with each other; there are several other ways to compare two numbers: `>`, `<`, `>=`, `<=`, `!=` and `==`, where the last two mean "not equal" and "exactly equal".[^2]
|
||||
|
||||
An important thing to note at this point is that this behavior is *different* with `String` variables.[^3] Comparing if two strings are equal by using `==` will not result in the behavior you might expect. Instead, you should compare two strings using `equals()` as follows:
|
||||
```java
|
||||
String s1 = "This is some text";
|
||||
String s2 = "This is also some text";
|
||||
if (s1.equals(s2)) {
|
||||
System.out.println("s1 and s2 are equal!");
|
||||
}
|
||||
```
|
||||
|
||||
## The `boolean` type
|
||||
A condition like this (which can either be `true` or `false`) can also be stored in a `boolean` variable[^4] whose state can then be checked using a similar `if` statement:
|
||||
```java
|
||||
int i = 15;
|
||||
boolean i27 = i >= 27;
|
||||
if (i27) {
|
||||
System.out.println("i is greater than or equal to 27!");
|
||||
}
|
||||
```
|
||||
The above code has the same effect as the code we looked at before. The cool thing about this method is that you can easily check if a condition *doesn't* hold true by simply adding an exclamation point `!` in front of any boolean variable:
|
||||
```java
|
||||
if (!i27) {
|
||||
System.out.println("i is NOT greater than or equal to 27!");
|
||||
}
|
||||
|
||||
// As you can see, this is especially useful when comparing strings
|
||||
String s1 = "This is some text";
|
||||
String s2 = "This is also some text";
|
||||
if (!s1.equals(s2)) {
|
||||
System.out.println("s1 and s2 are NOT equal!");
|
||||
}
|
||||
```
|
||||
|
||||
Additionally, two boolean variables (or simply two conditions) can be chained together in two ways:
|
||||
```java
|
||||
int i = 15;
|
||||
if (i == 12 || i == 13) {
|
||||
System.out.println("i is either 12 or 13!");
|
||||
}
|
||||
if (i >= 10 && i < 20) {
|
||||
System.out.println("i is somewhere between 10 and 20");
|
||||
}
|
||||
```
|
||||
As you can see in lines 2 to 4, two pipes `||` represent the `OR` operator: A combined condition using it holds true if the left side is true, or the right side is true, or both sides are true.
|
||||
As you can see in lines 5 to 7, two ampersands `&&` represent the `AND` operator: A combined condition using it holds true if *both* sides are also true.
|
||||
|
||||
You can also wrap your checks in parentheses `()` to create a more complex condition, similarly to how you would use them in a mathematical expression:
|
||||
```java
|
||||
int j = 10;
|
||||
int k = 15;
|
||||
boolean combination = (j == 12 && k == 13) || (j == 10 && k == 25);
|
||||
System.out.println(combination);
|
||||
```
|
||||
The above code will cause `true` to be printed if `j` equals 12 and `k` equals 13 *or* if `j` equals 10 and `k` equals 25. Otherwise, `false` will be printed.
|
||||
|
||||
## `else`
|
||||
If you want something *else* to happen if a certain condition doesn't hold true, then you can do something like the following:
|
||||
```java
|
||||
int i = 15;
|
||||
if (i >= 27) {
|
||||
System.out.println("i is greater than or equal to 27!");
|
||||
} else {
|
||||
System.out.println("i is less than 27 :(");
|
||||
}
|
||||
```
|
||||
As you can see, writing `else` after any `if` statement causes the code contained in the following curly braces `{}` to only be executed if the `if` statement's condition *isn't* true.
|
||||
|
||||
Optionally, you can also combine the `else` with another `if` statement to check for a different condition. You can do this as many times as you want:
|
||||
```java
|
||||
int i = 15;
|
||||
if (i >= 27) {
|
||||
System.out.println("i is greater than or equal to 27!");
|
||||
} else if (i <= 10) {
|
||||
System.out.println("i is less than 27, but also less than or equal to 10");
|
||||
} else {
|
||||
System.out.println("i is somewhere between 11 and 26");
|
||||
}
|
||||
```
|
||||
|
||||
# The `for` loop
|
||||
The `if` condition is already pretty powerful, because you can execute different code based on different situations. Another useful thing is the `for` loop. How it's written and what it does can be a bit complicated to understand at first, but I'll try to break the following example down for you:
|
||||
```java
|
||||
for (int index = 0; index < 3; index = index + 1) {
|
||||
System.out.println("The current index is " + index);
|
||||
}
|
||||
```
|
||||
This specific `for` loop causes the following to be printed to the console:
|
||||
```
|
||||
The current index is 0
|
||||
The current index is 1
|
||||
The current index is 2
|
||||
```
|
||||
As you might be able to tell from that, a `for` loop causes any number of instructions in it to be executed a certain amount of times.
|
||||
|
||||
Its structure is pretty similar to the `if` statement's: First, you write the word `for`, followed by some loop instructions inside parentheses `()`, and then you open curly braces `{}` which contain the instructions that should be executed multiple times. The loop instructions contain three parts, which are separated by semicolons `;`:
|
||||
- `int index = 0;` is the declaration of the *loop variable*: This is the instruction that will be executed *before* the loop starts running.
|
||||
- `index < 3;` is the *loop's condition*: Before every time the loop's content is run, a check is done to make sure that this condition is still true. If it's not true anymore, the loop stops running.
|
||||
- `index = index + 1` is the instruction that is executed *after* every time the loop's content has finished running.
|
||||
|
||||
So in the case of our loop, the following things happen:
|
||||
- The `index` variable is declared and set to 0.
|
||||
- `index < 3` is checked, which is obviously true.
|
||||
- The loop's content is run, which causes the print to the console.
|
||||
- `index = index + 1` is executed, which sets `index` to 1.
|
||||
- `index < 3` is checked, which is still true.
|
||||
- The loop's content is run again, and so on.
|
||||
|
||||
## `break`
|
||||
If you want to exit a `for` loop before its condition turns to `false`, you can use the `break;` statement as follows:
|
||||
```java
|
||||
for (int index = 0; index < 10000; index = index + 1) {
|
||||
System.out.println("The current index is " + index);
|
||||
|
||||
if (index >= 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
This loop has the same effect as the one we looked at before. Despite the loop condition specifying that it should repeat 10000 times, it is only repeated three times, because the condition on line 4 is evaluated every time and the loop is forced to stop running once it is true.
|
||||
|
||||
# Conclusion
|
||||
In this tutorial, you (hopefully) learned what the `if` and `for` statements are and how to use them. By now, you should be able to write some more complicated code. As a little exercise, you can try to solve the following problem using the things you learned in the last two tutorials:
|
||||
|
||||
> Given a variable `i` and another variable `exp`, calculate if the result of `i`<sup>`exp`</sup> (`i` to the power of `exp`) is less than or equal to the value of another variable `j` (and print the result to the console accordingly).
|
||||
|
||||
If you're stuck, you can check out my solution [here](https://gist.github.com/Ellpeck/999bafe352f84d5e1f09750e026d5bbf).
|
||||
|
||||
Thanks for reading this tutorial and I hope it helped you out! If you have any feedback or questions about it, you can click the discussion link below and ask me on Twitter, or join my Discord server using the widget on the main page. Happy coding!
|
||||
|
||||
***
|
||||
|
||||
[^1]: I'm covering this topic *before* I cover what exactly classes and methods are. I think that conditions and loops take importance here, because they're used broadly in every language as well as most programs, whereas object orientation is a feature specific to some languages, as well as specific to more "complex" programs. It's also somewhat complicated, and I want to explain it right, because when I learned Java, I didn't even remotely understand it correctly at first.
|
||||
|
||||
[^2]: Note that, when *comparing* two numbers, two equals signs `==` are used. This is different from *assigning a value* to a variable, which only uses one equals sign `=`.
|
||||
|
||||
[^3]: Why exactly this is the case will be discussed later when we get into object orientation. The different behavior mentioned here is the case for any variable types which aren't so-called *native types*. Any variable whose type starts with an uppercase letter is not a native type, because it derives from a *class*.
|
||||
|
||||
[^4]: Named after [George Boole](https://en.wikipedia.org/wiki/George_Boole), a mathematician.
|
|
@ -1,183 +1,183 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 3: (Static) Methods"
|
||||
summary: In this Java tutorial for beginners, we cover what (static) methods, parameters and return types are.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1182775985885847558
|
||||
---
|
||||
|
||||
I've been thinking about how to structure this tutorial a lot, and I decided to teach you all about methods *before* I get into object orientation, so you'll have to wait a little while longer before we get into the real nitty-gritty. To understand this one, you should've already read and understood tutorials 1 and 2. If you haven't, you can get to them by clicking the "Previous Post" button in the navigation bar.
|
||||
|
||||
So, here goes!
|
||||
|
||||
# Methods
|
||||
Methods are a way, in programming, to move certain code into a different location where it's more organized and, more importantly, where it can be called multiple times from multiple locations, possibly with different data. You'll see what exactly that means in a minute.
|
||||
|
||||
Let's create a simple method in our main class:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// I've omitted the code from the previous tutorials for readability
|
||||
}
|
||||
|
||||
public static void printInfo() {
|
||||
System.out.println("This is some important information!");
|
||||
}
|
||||
}
|
||||
```
|
||||
Let's take a look at the `printInfo` method I created. In this tutorial, we'll only be talking about `public` and `static` methods, so you'll just have to take that part for granted for now. Following that, you write `void` and then the name of your method (which can be anything you want), followed by parentheses `()` and then braces `{}`. Similarly to the `if` statement and the `for` loop, the method's content goes between those two curly braces, as I have done in this example with the print statement.
|
||||
|
||||
As you can see, all a method is is pretty much a collection of code. At this point, you might've already noticed that that is exactly what the `main` structure we've previously been writing all of our code into is: `main` is just another method.
|
||||
|
||||
To *call* a method, that is to have the code inside of it be executed, all you have to do is write the following:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// I've omitted the code from the previous tutorials for readability
|
||||
|
||||
printInfo();
|
||||
}
|
||||
|
||||
public static void printInfo() {
|
||||
System.out.println("This is some important information!");
|
||||
}
|
||||
}
|
||||
```
|
||||
There you go.
|
||||
|
||||
## Variables
|
||||
It should be noted at this point that variables which are declared *inside* of a method, like the ones we've been using in the first two tutorials, are known as `local variables`. What this means is that they only exist *inside* of the method they are declared in. Check out this example:
|
||||
```java
|
||||
// This method declares a variable i that is set to 0
|
||||
public static void methodOne() {
|
||||
int i = 0;
|
||||
}
|
||||
|
||||
// This method declares a *different* variable i that is set to 1
|
||||
public static void methodTwo() {
|
||||
int i = 1;
|
||||
}
|
||||
|
||||
// This method will cause an error if you paste it into your IDE:
|
||||
// You cannot declare two variables with the same name in one method.
|
||||
public static void erroringMethod() {
|
||||
int i = 0;
|
||||
int i = 1;
|
||||
}
|
||||
```
|
||||
This same behavior also counts for `if`, `for` and any other curly braces `{}` that you see: They close off any variables which are created inside of them and make them available to only that location.
|
||||
|
||||
# Parameters
|
||||
Now you might be wondering what the point of methods is if all they do is execute a predefined list of code. Well... you can actually make a method *accept* a set of data that they can use to do their processing. The data given to a method is called *parameters*, and these parameters are simply variables that you declare between the method's parentheses `()` right after its name.
|
||||
|
||||
Let's take the following example:
|
||||
```java
|
||||
public static void printInfo(String strg) {
|
||||
System.out.println("This is some important information about " + strg);
|
||||
}
|
||||
```
|
||||
I modified the method by adding the parameter `strg` to it, which is of the type `String`. What this means is that now, when calling the method, it expects you to give it a string that it can use to do stuff with (in this case, print it out).
|
||||
|
||||
If you add that parameter to the code we previously wrote, you might notice that your IDE is now displaying an error to you. You can't just do this anymore:
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
printInfo();
|
||||
}
|
||||
```
|
||||
As we just said, `printInfo` now wants us to give it a string whenever we call it. To give it that string, simply put it between the parentheses `()` of your method call like this:
|
||||
```java
|
||||
String someString = "Some String";
|
||||
printInfo(someString);
|
||||
|
||||
// or, optionally, the shorter form:
|
||||
printInfo("Some String");
|
||||
```
|
||||
Running your code now should cause `This is some important information about Some String` to be displayed in your console.
|
||||
|
||||
In case you're thinking "I've seen that somewhere before", then you would be correct: This is exactly the same thing you do when you try to print something out to the console: You call the `println` method and give it the text you want to print out as the parameter.
|
||||
|
||||
The cool thing is that a method can also accept *multiple* parameters, so multiple bits of data can be passed into it when calling it. Let's look at this example:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
printInfo("Some String", 5);
|
||||
}
|
||||
|
||||
public static void printInfo(String strg, int amount) {
|
||||
for (int i = 0; i < amount; i = i + 1) {
|
||||
System.out.println("This is some important information about " + strg);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the `printInfo` method now takes two parameters, separated by a comma `,`. The code inside of the method should already be familiar to you: It's a simple for loop that prints the same message `amount` times.
|
||||
|
||||
So now, we have something that also demonstrates pretty well the versatility of methods: We can now call `printInfo` with any information that will be printed any amount of times:
|
||||
```java
|
||||
printInfo("Some String", 5);
|
||||
printInfo("Some other String", 10);
|
||||
```
|
||||
|
||||
# Returning
|
||||
Another thing that methods can do that is really useful is the ability to *return* certain data. What this means is that they can, after their execution finishes, take the data they created or modified and give it back to the caller:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
int tenSquared = square(10);
|
||||
System.out.println(tenSquared); // prints 100
|
||||
System.out.println(square(5)); // prints 25
|
||||
}
|
||||
|
||||
public static int square(int i) {
|
||||
return i * i;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I created a method `square` that returns its parameter `i`, but squared. To make a method return a value, two things have to be done:
|
||||
- The method's *return type* has to be declared. For methods that don't return anything, the return type is `void`. For methods that return something, just replace `void` with the *type of variable* that it returns.
|
||||
- To actually return a specific value after it has been calculated, just type `return`, followed by the value and a semicolon `;`.
|
||||
|
||||
Now, this method can be used as if it were just another number: We can set variables to it and print it out. But instead of it being just another number, it actually executes the code inside it every time.
|
||||
|
||||
## Stopping execution
|
||||
A thing that should be noted about returning is that any code that comes after a return statement will *not* be executed. In other words: After returning a value, a method will stop its execution, no matter what comes next.
|
||||
```java
|
||||
public static int square(int i) {
|
||||
return i * i;
|
||||
System.out.println("This will never be called");
|
||||
}
|
||||
```
|
||||
In this specific case, that isn't really useful - why write code that can never be executed? But take this other example:
|
||||
```java
|
||||
public static boolean isIGreaterThanJ(int i, int j) {
|
||||
if (i > j) {
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println("i is NOT greater than j!");
|
||||
return false;
|
||||
}
|
||||
```
|
||||
In this example, the print statement will not be executed if `i` is greater than `j` despite the fact that it's not wrapped in an `else`, because the method gets returned out of before it can be called.
|
||||
|
||||
## Requirements
|
||||
If you create a method that has a return type other than `void` (which, again, means "this method doesn't return anything"), then every possible path that the execution can take inside the method *needs* to return *something*.
|
||||
|
||||
What this means is that you can't have something like this:
|
||||
```java
|
||||
public static boolean isIGreaterThanJ(int i, int j) {
|
||||
if (i > j) {
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println("i is NOT greater than j!");
|
||||
}
|
||||
```
|
||||
Because when `i` is *not* greater than `j`, the print statement will be executed but then, the method doesn't know what value to return, so this code will give out an error before it even tries to execute.
|
||||
|
||||
# Conclusion
|
||||
So yea, that's pretty much everything important there is to know about (static) methods. In one of the next tutorials, we'll finally get into actual object orientation and we'll soon be taking a look at non-static methods, which are even more useful than static methods.
|
||||
|
||||
As a little exercise, you might want to create some methods with different return types and different parameters and call them. Have some fun!
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 3: (Static) Methods"
|
||||
description: In this Java tutorial for beginners, we cover what (static) methods, parameters and return types are.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1182775985885847558
|
||||
---
|
||||
|
||||
I've been thinking about how to structure this tutorial a lot, and I decided to teach you all about methods *before* I get into object orientation, so you'll have to wait a little while longer before we get into the real nitty-gritty. To understand this one, you should've already read and understood tutorials 1 and 2. If you haven't, you can get to them by clicking the "Previous Post" button in the navigation bar.
|
||||
|
||||
So, here goes!
|
||||
|
||||
# Methods
|
||||
Methods are a way, in programming, to move certain code into a different location where it's more organized and, more importantly, where it can be called multiple times from multiple locations, possibly with different data. You'll see what exactly that means in a minute.
|
||||
|
||||
Let's create a simple method in our main class:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// I've omitted the code from the previous tutorials for readability
|
||||
}
|
||||
|
||||
public static void printInfo() {
|
||||
System.out.println("This is some important information!");
|
||||
}
|
||||
}
|
||||
```
|
||||
Let's take a look at the `printInfo` method I created. In this tutorial, we'll only be talking about `public` and `static` methods, so you'll just have to take that part for granted for now. Following that, you write `void` and then the name of your method (which can be anything you want), followed by parentheses `()` and then braces `{}`. Similarly to the `if` statement and the `for` loop, the method's content goes between those two curly braces, as I have done in this example with the print statement.
|
||||
|
||||
As you can see, all a method is is pretty much a collection of code. At this point, you might've already noticed that that is exactly what the `main` structure we've previously been writing all of our code into is: `main` is just another method.
|
||||
|
||||
To *call* a method, that is to have the code inside of it be executed, all you have to do is write the following:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// I've omitted the code from the previous tutorials for readability
|
||||
|
||||
printInfo();
|
||||
}
|
||||
|
||||
public static void printInfo() {
|
||||
System.out.println("This is some important information!");
|
||||
}
|
||||
}
|
||||
```
|
||||
There you go.
|
||||
|
||||
## Variables
|
||||
It should be noted at this point that variables which are declared *inside* of a method, like the ones we've been using in the first two tutorials, are known as `local variables`. What this means is that they only exist *inside* of the method they are declared in. Check out this example:
|
||||
```java
|
||||
// This method declares a variable i that is set to 0
|
||||
public static void methodOne() {
|
||||
int i = 0;
|
||||
}
|
||||
|
||||
// This method declares a *different* variable i that is set to 1
|
||||
public static void methodTwo() {
|
||||
int i = 1;
|
||||
}
|
||||
|
||||
// This method will cause an error if you paste it into your IDE:
|
||||
// You cannot declare two variables with the same name in one method.
|
||||
public static void erroringMethod() {
|
||||
int i = 0;
|
||||
int i = 1;
|
||||
}
|
||||
```
|
||||
This same behavior also counts for `if`, `for` and any other curly braces `{}` that you see: They close off any variables which are created inside of them and make them available to only that location.
|
||||
|
||||
# Parameters
|
||||
Now you might be wondering what the point of methods is if all they do is execute a predefined list of code. Well... you can actually make a method *accept* a set of data that they can use to do their processing. The data given to a method is called *parameters*, and these parameters are simply variables that you declare between the method's parentheses `()` right after its name.
|
||||
|
||||
Let's take the following example:
|
||||
```java
|
||||
public static void printInfo(String strg) {
|
||||
System.out.println("This is some important information about " + strg);
|
||||
}
|
||||
```
|
||||
I modified the method by adding the parameter `strg` to it, which is of the type `String`. What this means is that now, when calling the method, it expects you to give it a string that it can use to do stuff with (in this case, print it out).
|
||||
|
||||
If you add that parameter to the code we previously wrote, you might notice that your IDE is now displaying an error to you. You can't just do this anymore:
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
printInfo();
|
||||
}
|
||||
```
|
||||
As we just said, `printInfo` now wants us to give it a string whenever we call it. To give it that string, simply put it between the parentheses `()` of your method call like this:
|
||||
```java
|
||||
String someString = "Some String";
|
||||
printInfo(someString);
|
||||
|
||||
// or, optionally, the shorter form:
|
||||
printInfo("Some String");
|
||||
```
|
||||
Running your code now should cause `This is some important information about Some String` to be displayed in your console.
|
||||
|
||||
In case you're thinking "I've seen that somewhere before", then you would be correct: This is exactly the same thing you do when you try to print something out to the console: You call the `println` method and give it the text you want to print out as the parameter.
|
||||
|
||||
The cool thing is that a method can also accept *multiple* parameters, so multiple bits of data can be passed into it when calling it. Let's look at this example:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
printInfo("Some String", 5);
|
||||
}
|
||||
|
||||
public static void printInfo(String strg, int amount) {
|
||||
for (int i = 0; i < amount; i = i + 1) {
|
||||
System.out.println("This is some important information about " + strg);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the `printInfo` method now takes two parameters, separated by a comma `,`. The code inside of the method should already be familiar to you: It's a simple for loop that prints the same message `amount` times.
|
||||
|
||||
So now, we have something that also demonstrates pretty well the versatility of methods: We can now call `printInfo` with any information that will be printed any amount of times:
|
||||
```java
|
||||
printInfo("Some String", 5);
|
||||
printInfo("Some other String", 10);
|
||||
```
|
||||
|
||||
# Returning
|
||||
Another thing that methods can do that is really useful is the ability to *return* certain data. What this means is that they can, after their execution finishes, take the data they created or modified and give it back to the caller:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
int tenSquared = square(10);
|
||||
System.out.println(tenSquared); // prints 100
|
||||
System.out.println(square(5)); // prints 25
|
||||
}
|
||||
|
||||
public static int square(int i) {
|
||||
return i * i;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I created a method `square` that returns its parameter `i`, but squared. To make a method return a value, two things have to be done:
|
||||
- The method's *return type* has to be declared. For methods that don't return anything, the return type is `void`. For methods that return something, just replace `void` with the *type of variable* that it returns.
|
||||
- To actually return a specific value after it has been calculated, just type `return`, followed by the value and a semicolon `;`.
|
||||
|
||||
Now, this method can be used as if it were just another number: We can set variables to it and print it out. But instead of it being just another number, it actually executes the code inside it every time.
|
||||
|
||||
## Stopping execution
|
||||
A thing that should be noted about returning is that any code that comes after a return statement will *not* be executed. In other words: After returning a value, a method will stop its execution, no matter what comes next.
|
||||
```java
|
||||
public static int square(int i) {
|
||||
return i * i;
|
||||
System.out.println("This will never be called");
|
||||
}
|
||||
```
|
||||
In this specific case, that isn't really useful - why write code that can never be executed? But take this other example:
|
||||
```java
|
||||
public static boolean isIGreaterThanJ(int i, int j) {
|
||||
if (i > j) {
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println("i is NOT greater than j!");
|
||||
return false;
|
||||
}
|
||||
```
|
||||
In this example, the print statement will not be executed if `i` is greater than `j` despite the fact that it's not wrapped in an `else`, because the method gets returned out of before it can be called.
|
||||
|
||||
## Requirements
|
||||
If you create a method that has a return type other than `void` (which, again, means "this method doesn't return anything"), then every possible path that the execution can take inside the method *needs* to return *something*.
|
||||
|
||||
What this means is that you can't have something like this:
|
||||
```java
|
||||
public static boolean isIGreaterThanJ(int i, int j) {
|
||||
if (i > j) {
|
||||
return true;
|
||||
}
|
||||
|
||||
System.out.println("i is NOT greater than j!");
|
||||
}
|
||||
```
|
||||
Because when `i` is *not* greater than `j`, the print statement will be executed but then, the method doesn't know what value to return, so this code will give out an error before it even tries to execute.
|
||||
|
||||
# Conclusion
|
||||
So yea, that's pretty much everything important there is to know about (static) methods. In one of the next tutorials, we'll finally get into actual object orientation and we'll soon be taking a look at non-static methods, which are even more useful than static methods.
|
||||
|
||||
As a little exercise, you might want to create some methods with different return types and different parameters and call them. Have some fun!
|
||||
|
||||
I hope you enjoyed reading, and of course: Happy coding!
|
|
@ -1,217 +1,217 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 4: Classes and Objects"
|
||||
summary: In this Java tutorial for beginners, we cover the basics of creating classes with a constructor, some fields and some methods and creating objects of them.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1183857460660101133
|
||||
---
|
||||
|
||||
So you've gotten far enough into Java now that you'll finally be able to learn about what this "object orientation" jazz is that everyone keeps talking about. I feel like this is a somewhat complicated topic to explain, so bear with me.
|
||||
|
||||
# Classes
|
||||
So far in the tutorial, we've only ever used classes as basic storage containers for variables and methods. Let's stick with that for another moment while we create a simple `Utility` class that has a method we might want to use throughout our program. We'll create it in a new file (Right-Click on `src`, `New`, `Java Class` in IntelliJ) like so:
|
||||
```java
|
||||
public class Utility {
|
||||
}
|
||||
```
|
||||
As you can see, this structure is similar to that of our `Main` class: The word `public`, followed by the word `class`, followed by the name of the class (which, in 99% of cases, should match the file name), followed by curly braces `{}`, which, as you might expect by now, contain the content of our class.
|
||||
|
||||
So let's add a method to it that, I don't know, returns the absolute value of an integer passed to it. We'll call this one `abs`, for "absolute".[^1]
|
||||
```java
|
||||
public class Utility {
|
||||
public static int abs(int num) {
|
||||
if (num < 0) {
|
||||
return -num;
|
||||
} else {
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
By now, this code should be pretty easy for you to understand: We've added a method called `abs` that takes in an integer parameter called `num`, and if `num` is negative, then we return the negated value of num (`-num`).
|
||||
|
||||
Now, because this method is in a different class to the one we might want to use the method in (`Main` in our case), we have to explicitly mention the class the method is in by prefixing the class' name followed by a dot `.` when calling it, like so:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// This is our usual main method
|
||||
|
||||
int abs = Utility.abs(-17);
|
||||
System.out.println(abs);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Objects
|
||||
Let's finally move away from `static` methods and into object orientation.[^2] I'll give you a quick, made-by-me outline of what object orientation even *means*, based on an example that might be a bit easier for you to understand.
|
||||
|
||||
Let's imagine we're not talking about objects, but *tables*. When you say something like "A table has four legs", you're not talking about a *specific* table, but rather, you're talking about the *concept* of what a table is. In Java, this is what a class is. Now, when you say something like "This table has four legs" while pointing to the table on the other side of the room, then you're talking about a very specific table, not just a concept anymore. In Java, this is what an object is. When we now say "object oriented", we merely mean "code that makes use of objects."
|
||||
|
||||
Another way to think of it is that classes are *blueprints* for certain things, and objects are the actual constructions that were created by following those blueprints.
|
||||
|
||||
## Creating Objects
|
||||
So let's stick with this table example for now. First, we'll create a class called `Table` like so:
|
||||
```java
|
||||
public class Table {
|
||||
}
|
||||
```
|
||||
So now, we have a very basic blueprint of a table.
|
||||
|
||||
Now, let's go back into our main class and actually create a *specific* table like so:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// This is our usual main method
|
||||
|
||||
Table myTable;
|
||||
myTable = new Table();
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the structure of line 5 is the same as how we usually declare variables: `Table` is the variable type (this is where we usually put `int` or `String`), and `myTable` is the name of the variable. Line 6 is where the new stuff happens, however: We set the variable's *value* to a newly created *instance* of the `Table` class. This is us creating a specific table following the blueprint that is the `Table` class: We write `new`, then the class' name, and then opening and closing parentheses `()`.
|
||||
|
||||
# Fields
|
||||
What we have so far isn't really that interesting yet - our table doesn't really have any properties yet. But now, we can actually add *fields* to our class: Certain variables that each object will share, but whose values can also be *different* for each object. Fields are declared like normal variables, but are placed at the top of a class, prefixed with the `public` keyword like so:
|
||||
```java
|
||||
public class Table {
|
||||
public int legAmount;
|
||||
}
|
||||
```
|
||||
Now, each table *instance* can have its amount of legs modified as well as displayed like so:
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
myTable.legAmount = 4;
|
||||
System.out.println("My table has " + myTable.legAmount + " legs");
|
||||
```
|
||||
As you can see, to access an object's fields, all you have to do is write the variable name, followed by a dot `.`, followed by the field's name.
|
||||
|
||||
The important thing to know here is that this variable is now unique for *every table instance you create*, meaning the following code...
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
Table myOtherTable = new Table();
|
||||
|
||||
myTable.legAmount = 4;
|
||||
myOtherTable.legAmount = 25;
|
||||
|
||||
System.out.println("My table has " + myTable.legAmount + " legs");
|
||||
System.out.println("My other table has " + myOtherTable.legAmount + " legs");
|
||||
```
|
||||
...will print out `My table has 4 legs`, followed by `My other table has 25 legs`.
|
||||
|
||||
# Methods
|
||||
Obviously, you already know what methods are, but we can finally get rid of the `static` keyword for those as well. Similarly to what we can do with fields, we can also add methods to classes that can do unique things based on the object they're being called for. Let's take a look at the following code:
|
||||
```java
|
||||
public class Table {
|
||||
|
||||
public int legAmount;
|
||||
|
||||
public void printLegAmount() {
|
||||
System.out.println("I have a certain amount of legs");
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I've added a (non-static) method to this class called `printLegAmount`. Now we can change the code in our `Main` class to just call that method instead:
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
myTable.legAmount = 4;
|
||||
myTable.printLegAmount();
|
||||
```
|
||||
|
||||
## The `this` keyword
|
||||
Now that specific example isn't really that useful yet, because every single table we create will print out `I have a certain amount of legs`, when it would really be nicer if the table printed out its amount of legs stored in the `legAmount` variable.
|
||||
|
||||
That's exactly what the `this` keyword is for.[^3] Let's modify our method from before:
|
||||
```java
|
||||
public class Table {
|
||||
|
||||
public int legAmount;
|
||||
|
||||
public void printLegAmount() {
|
||||
System.out.println("I have " + this.legAmount + " legs");
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, `this` is being used here similarly to how we were using `myTable.legAmount` earlier. That has a good reason: `this` also refers to an object. However, the object that `this` refers to is *the current one*. When calling a method like `printLegAmount` for a specific object (`myTable` in our case), the `this` keyword will always refer to that object.
|
||||
|
||||
So if we have code like this...
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
Table myOtherTable = new Table();
|
||||
|
||||
myTable.legAmount = 4;
|
||||
myOtherTable.legAmount = 25;
|
||||
|
||||
myTable.printLegAmount();
|
||||
myOtherTable.printLegAmount();
|
||||
```
|
||||
...then the result will be the same as before: `My table has 4 legs`, followed by `My other table has 25 legs`, because in `myTable.printLegAmount()`, `this` will be `myTable`, and in `myOtherTable.printLegAmount()`, `this` will be `myOtherTable`.
|
||||
|
||||
# Constructors
|
||||
Constructors are a special kind of method in Java. You can't really execute them manually, but instead, they're automatically called every time a new instance is created (so every time you use the `new` keyword).
|
||||
|
||||
Let's look at the following example, which adds a constructor to our `Table` class that automatically sets the `legAmount` variable to 4.
|
||||
```java
|
||||
public class Table {
|
||||
|
||||
public int legAmount;
|
||||
|
||||
// The constructor
|
||||
public Table() {
|
||||
this.legAmount = 4;
|
||||
}
|
||||
|
||||
public void printLegAmount() {
|
||||
System.out.println("I have " + this.legAmount + " legs");
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, a constructor is different from other methods in that it *doesn't have a name*, and that its return type is *the same as the class it is in*.
|
||||
|
||||
So now, any instance of `Table` that we create will automatically have a leg amount of 4:
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
myTable.printLegAmount(); // "I have 4 legs"
|
||||
```
|
||||
|
||||
## Constructor parameters
|
||||
Just like in any other method, we can add a set of variables that the constructor accepts (parameters). In our case, we could make a table request a `legAmount` when it's initialized as follows:
|
||||
```java
|
||||
// The constructor
|
||||
public Table(int legs) {
|
||||
this.legAmount = legs;
|
||||
}
|
||||
```
|
||||
Now, when creating a new instance of `Table`, we have to actually give it a leg amount that it should start with:
|
||||
```java
|
||||
Table myTable = new Table(4);
|
||||
```
|
||||
|
||||
# So what about `static`?
|
||||
As you have learned throughout this tutorial, non-static methods and variables inside of classes have a key property: They're unique for every object that is created of that class. So why have we been using `static` throughout both our `Main` and our `Utility` classes?
|
||||
|
||||
The `static` keyword tells any field or method that it should *not* be unique for every object that is created. Even if we created an instance of our `Main` class (`new Main()`), for example, the `main` method would not be unique for that instance, because it is marked with the `static` keyword. This also means that using the `this` keyword would make no sense in a static method (which object would it reference?), which is why doing so doesn't work.
|
||||
|
||||
Similarly, if we made the `abs` method in our `Utility` class non-static, then we could *not* access it simply by typing `Utility.abs()`, because the method would be unique for every object that is created of the class. We *could* then use the `abs` method if we first created an instance of the `Utility` class (`new Utility()`).
|
||||
|
||||
# Conclusion
|
||||
So yea, that's quite a lot of information for you to process. The introduction to objects is a pretty big step, but it also allows for a lot of cool new stuff that you can learn. In the next couple tutorials, we'll expand on the concept of objects and learn some more stuff that you can do with them to make them even more useful.
|
||||
|
||||
For now, though, I'll leave you with this little exercise you can do to facilitate what you learned about objects and to get a better understanding of how useful they are:[^4]
|
||||
|
||||
> Let's imagine you're managing a small car dealership. You want to have a way of managing all of the cars you have in stock. This includes keeping track of their brand names, their horsepower, their license plate texts and their mileage. Currently, you have four different cars in stock, and you want your program to print out all of the information about all of the cars.
|
||||
|
||||
If you're stuck, you can [get some hints](https://gist.github.com/Ellpeck/462022597659f554fdd75663359480d3) or [look at my solution](https://gist.github.com/Ellpeck/7a0f31306d05473c10e8bca1685510a4).
|
||||
|
||||
Next time, we'll be talking about arrays and lists.[^5] Happy coding!
|
||||
|
||||
***
|
||||
|
||||
[^1]: Java's default `Math` class already has an `abs` method that does this same thing, but for the sake of this tutorial, we'll ignore it (because I can't think of any other utility method to add, in all honesty).
|
||||
|
||||
[^2]: Note that I explain why we're omitting the `static` keyword from now on a bit later in this tutorial.
|
||||
|
||||
[^3]: In a lot of cases, using the `this` keyword is actually optional and it can just be left out altogether. However, I personally think that it increases code readability quite a bit and that it helps a lot with understanding how objects work, so I advise you to use it.
|
||||
|
||||
[^4]: This example is one that almost every instructor uses. It might be a bit boring and ridiculous, but it's simple and helps understanding the concept, so I also like using it when teaching people how to code.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 4: Classes and Objects"
|
||||
description: In this Java tutorial for beginners, we cover the basics of creating classes with a constructor, some fields and some methods and creating objects of them.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1183857460660101133
|
||||
---
|
||||
|
||||
So you've gotten far enough into Java now that you'll finally be able to learn about what this "object orientation" jazz is that everyone keeps talking about. I feel like this is a somewhat complicated topic to explain, so bear with me.
|
||||
|
||||
# Classes
|
||||
So far in the tutorial, we've only ever used classes as basic storage containers for variables and methods. Let's stick with that for another moment while we create a simple `Utility` class that has a method we might want to use throughout our program. We'll create it in a new file (Right-Click on `src`, `New`, `Java Class` in IntelliJ) like so:
|
||||
```java
|
||||
public class Utility {
|
||||
}
|
||||
```
|
||||
As you can see, this structure is similar to that of our `Main` class: The word `public`, followed by the word `class`, followed by the name of the class (which, in 99% of cases, should match the file name), followed by curly braces `{}`, which, as you might expect by now, contain the content of our class.
|
||||
|
||||
So let's add a method to it that, I don't know, returns the absolute value of an integer passed to it. We'll call this one `abs`, for "absolute".[^1]
|
||||
```java
|
||||
public class Utility {
|
||||
public static int abs(int num) {
|
||||
if (num < 0) {
|
||||
return -num;
|
||||
} else {
|
||||
return num;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
By now, this code should be pretty easy for you to understand: We've added a method called `abs` that takes in an integer parameter called `num`, and if `num` is negative, then we return the negated value of num (`-num`).
|
||||
|
||||
Now, because this method is in a different class to the one we might want to use the method in (`Main` in our case), we have to explicitly mention the class the method is in by prefixing the class' name followed by a dot `.` when calling it, like so:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// This is our usual main method
|
||||
|
||||
int abs = Utility.abs(-17);
|
||||
System.out.println(abs);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Objects
|
||||
Let's finally move away from `static` methods and into object orientation.[^2] I'll give you a quick, made-by-me outline of what object orientation even *means*, based on an example that might be a bit easier for you to understand.
|
||||
|
||||
Let's imagine we're not talking about objects, but *tables*. When you say something like "A table has four legs", you're not talking about a *specific* table, but rather, you're talking about the *concept* of what a table is. In Java, this is what a class is. Now, when you say something like "This table has four legs" while pointing to the table on the other side of the room, then you're talking about a very specific table, not just a concept anymore. In Java, this is what an object is. When we now say "object oriented", we merely mean "code that makes use of objects."
|
||||
|
||||
Another way to think of it is that classes are *blueprints* for certain things, and objects are the actual constructions that were created by following those blueprints.
|
||||
|
||||
## Creating Objects
|
||||
So let's stick with this table example for now. First, we'll create a class called `Table` like so:
|
||||
```java
|
||||
public class Table {
|
||||
}
|
||||
```
|
||||
So now, we have a very basic blueprint of a table.
|
||||
|
||||
Now, let's go back into our main class and actually create a *specific* table like so:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
// This is our usual main method
|
||||
|
||||
Table myTable;
|
||||
myTable = new Table();
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the structure of line 5 is the same as how we usually declare variables: `Table` is the variable type (this is where we usually put `int` or `String`), and `myTable` is the name of the variable. Line 6 is where the new stuff happens, however: We set the variable's *value* to a newly created *instance* of the `Table` class. This is us creating a specific table following the blueprint that is the `Table` class: We write `new`, then the class' name, and then opening and closing parentheses `()`.
|
||||
|
||||
# Fields
|
||||
What we have so far isn't really that interesting yet - our table doesn't really have any properties yet. But now, we can actually add *fields* to our class: Certain variables that each object will share, but whose values can also be *different* for each object. Fields are declared like normal variables, but are placed at the top of a class, prefixed with the `public` keyword like so:
|
||||
```java
|
||||
public class Table {
|
||||
public int legAmount;
|
||||
}
|
||||
```
|
||||
Now, each table *instance* can have its amount of legs modified as well as displayed like so:
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
myTable.legAmount = 4;
|
||||
System.out.println("My table has " + myTable.legAmount + " legs");
|
||||
```
|
||||
As you can see, to access an object's fields, all you have to do is write the variable name, followed by a dot `.`, followed by the field's name.
|
||||
|
||||
The important thing to know here is that this variable is now unique for *every table instance you create*, meaning the following code...
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
Table myOtherTable = new Table();
|
||||
|
||||
myTable.legAmount = 4;
|
||||
myOtherTable.legAmount = 25;
|
||||
|
||||
System.out.println("My table has " + myTable.legAmount + " legs");
|
||||
System.out.println("My other table has " + myOtherTable.legAmount + " legs");
|
||||
```
|
||||
...will print out `My table has 4 legs`, followed by `My other table has 25 legs`.
|
||||
|
||||
# Methods
|
||||
Obviously, you already know what methods are, but we can finally get rid of the `static` keyword for those as well. Similarly to what we can do with fields, we can also add methods to classes that can do unique things based on the object they're being called for. Let's take a look at the following code:
|
||||
```java
|
||||
public class Table {
|
||||
|
||||
public int legAmount;
|
||||
|
||||
public void printLegAmount() {
|
||||
System.out.println("I have a certain amount of legs");
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I've added a (non-static) method to this class called `printLegAmount`. Now we can change the code in our `Main` class to just call that method instead:
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
myTable.legAmount = 4;
|
||||
myTable.printLegAmount();
|
||||
```
|
||||
|
||||
## The `this` keyword
|
||||
Now that specific example isn't really that useful yet, because every single table we create will print out `I have a certain amount of legs`, when it would really be nicer if the table printed out its amount of legs stored in the `legAmount` variable.
|
||||
|
||||
That's exactly what the `this` keyword is for.[^3] Let's modify our method from before:
|
||||
```java
|
||||
public class Table {
|
||||
|
||||
public int legAmount;
|
||||
|
||||
public void printLegAmount() {
|
||||
System.out.println("I have " + this.legAmount + " legs");
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, `this` is being used here similarly to how we were using `myTable.legAmount` earlier. That has a good reason: `this` also refers to an object. However, the object that `this` refers to is *the current one*. When calling a method like `printLegAmount` for a specific object (`myTable` in our case), the `this` keyword will always refer to that object.
|
||||
|
||||
So if we have code like this...
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
Table myOtherTable = new Table();
|
||||
|
||||
myTable.legAmount = 4;
|
||||
myOtherTable.legAmount = 25;
|
||||
|
||||
myTable.printLegAmount();
|
||||
myOtherTable.printLegAmount();
|
||||
```
|
||||
...then the result will be the same as before: `My table has 4 legs`, followed by `My other table has 25 legs`, because in `myTable.printLegAmount()`, `this` will be `myTable`, and in `myOtherTable.printLegAmount()`, `this` will be `myOtherTable`.
|
||||
|
||||
# Constructors
|
||||
Constructors are a special kind of method in Java. You can't really execute them manually, but instead, they're automatically called every time a new instance is created (so every time you use the `new` keyword).
|
||||
|
||||
Let's look at the following example, which adds a constructor to our `Table` class that automatically sets the `legAmount` variable to 4.
|
||||
```java
|
||||
public class Table {
|
||||
|
||||
public int legAmount;
|
||||
|
||||
// The constructor
|
||||
public Table() {
|
||||
this.legAmount = 4;
|
||||
}
|
||||
|
||||
public void printLegAmount() {
|
||||
System.out.println("I have " + this.legAmount + " legs");
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, a constructor is different from other methods in that it *doesn't have a name*, and that its return type is *the same as the class it is in*.
|
||||
|
||||
So now, any instance of `Table` that we create will automatically have a leg amount of 4:
|
||||
```java
|
||||
Table myTable = new Table();
|
||||
myTable.printLegAmount(); // "I have 4 legs"
|
||||
```
|
||||
|
||||
## Constructor parameters
|
||||
Just like in any other method, we can add a set of variables that the constructor accepts (parameters). In our case, we could make a table request a `legAmount` when it's initialized as follows:
|
||||
```java
|
||||
// The constructor
|
||||
public Table(int legs) {
|
||||
this.legAmount = legs;
|
||||
}
|
||||
```
|
||||
Now, when creating a new instance of `Table`, we have to actually give it a leg amount that it should start with:
|
||||
```java
|
||||
Table myTable = new Table(4);
|
||||
```
|
||||
|
||||
# So what about `static`?
|
||||
As you have learned throughout this tutorial, non-static methods and variables inside of classes have a key property: They're unique for every object that is created of that class. So why have we been using `static` throughout both our `Main` and our `Utility` classes?
|
||||
|
||||
The `static` keyword tells any field or method that it should *not* be unique for every object that is created. Even if we created an instance of our `Main` class (`new Main()`), for example, the `main` method would not be unique for that instance, because it is marked with the `static` keyword. This also means that using the `this` keyword would make no sense in a static method (which object would it reference?), which is why doing so doesn't work.
|
||||
|
||||
Similarly, if we made the `abs` method in our `Utility` class non-static, then we could *not* access it simply by typing `Utility.abs()`, because the method would be unique for every object that is created of the class. We *could* then use the `abs` method if we first created an instance of the `Utility` class (`new Utility()`).
|
||||
|
||||
# Conclusion
|
||||
So yea, that's quite a lot of information for you to process. The introduction to objects is a pretty big step, but it also allows for a lot of cool new stuff that you can learn. In the next couple tutorials, we'll expand on the concept of objects and learn some more stuff that you can do with them to make them even more useful.
|
||||
|
||||
For now, though, I'll leave you with this little exercise you can do to facilitate what you learned about objects and to get a better understanding of how useful they are:[^4]
|
||||
|
||||
> Let's imagine you're managing a small car dealership. You want to have a way of managing all of the cars you have in stock. This includes keeping track of their brand names, their horsepower, their license plate texts and their mileage. Currently, you have four different cars in stock, and you want your program to print out all of the information about all of the cars.
|
||||
|
||||
If you're stuck, you can [get some hints](https://gist.github.com/Ellpeck/462022597659f554fdd75663359480d3) or [look at my solution](https://gist.github.com/Ellpeck/7a0f31306d05473c10e8bca1685510a4).
|
||||
|
||||
Next time, we'll be talking about arrays and lists.[^5] Happy coding!
|
||||
|
||||
***
|
||||
|
||||
[^1]: Java's default `Math` class already has an `abs` method that does this same thing, but for the sake of this tutorial, we'll ignore it (because I can't think of any other utility method to add, in all honesty).
|
||||
|
||||
[^2]: Note that I explain why we're omitting the `static` keyword from now on a bit later in this tutorial.
|
||||
|
||||
[^3]: In a lot of cases, using the `this` keyword is actually optional and it can just be left out altogether. However, I personally think that it increases code readability quite a bit and that it helps a lot with understanding how objects work, so I advise you to use it.
|
||||
|
||||
[^4]: This example is one that almost every instructor uses. It might be a bit boring and ridiculous, but it's simple and helps understanding the concept, so I also like using it when teaching people how to code.
|
||||
|
||||
[^5]: Note that there is also another huge topic to talk about when it comes to object orientation, which is *pointers* and how Java manages objects and their assignment to variables (including pass-by-reference and the like). I'll cover that soon. I promise. <3
|
|
@ -1,174 +1,174 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 5: Things I Left Out So Far"
|
||||
summary: In this Java tutorial for beginners, we cover some shorthands, some more data types, the difference between pass-by-reference and pass-by-value, null, as well as arrays and lists.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1184894859133509632
|
||||
---
|
||||
|
||||
After that complicated stuff we did in the last tutorial, how about we take it down a notch in this one and talk about some additional things that I haven't mentioned this far, but that will still be very useful to you as a programmer. Most of these things won't really have much connection to each other, but I'll give you an example at the end of this tutorial that combines some of them into a single use case.
|
||||
|
||||
# Shorthands
|
||||
Java has some shorthands to make addition and other mathematical operations faster. As there isn't really that much to explain (they're really just vocabulary), here's a list of them:
|
||||
```java
|
||||
// These two statements are equivalent
|
||||
// (This also works with all other math operators)
|
||||
i = i + 2;
|
||||
i += 2;
|
||||
|
||||
// When adding or subtracting 1, you can just do this:
|
||||
i++;
|
||||
i--;
|
||||
```
|
||||
|
||||
# Primitive Types
|
||||
Primitive types (also called *native types*) are variable types in a language that are baked into the very foundation of the language. That means they don't derive from a class, but they just exist as part of the language itself. The two primitive types you already know are `int` (32 bit integers) and `boolean` (`true` and `false`). In Java, primitive types always start with a lowercase letter (instead of an uppercase letter for classes).
|
||||
|
||||
Along with `int` and `boolean`, there are some more primitive types that could come in useful when programming. Here are the ones I haven't mentioned yet, quickly summed up:
|
||||
```java
|
||||
// "char" represents a single character.
|
||||
// Characters use single quotes ' rather than double quotes " (which are reserved for strings).
|
||||
char character = 'A';
|
||||
char fourthChar = "Hello World".charAt(4); // o
|
||||
|
||||
// "double" represents a 64bit floating point number
|
||||
// which is a number with a decimal point
|
||||
// It's called a double because it has double the precision of float (see below)
|
||||
double d = 3.14;
|
||||
|
||||
// "float" represents a 32bit floating point number (less precise than double).
|
||||
// To differentiate floats from doubles and ints, you have to append an "F".
|
||||
float f = 12.5F;
|
||||
|
||||
// "long" represents a 64bit integer (which can store a lot higher numbers than int)
|
||||
// To differentiate longs from ints, you have to append an "L".
|
||||
long l = 9223372036854775807L;
|
||||
|
||||
// "short" represents a 16bit integer
|
||||
short s = 32767;
|
||||
|
||||
// "byte" represents an 8bit integer
|
||||
byte b = 127;
|
||||
```
|
||||
|
||||
## What about `String`?
|
||||
Oh boy. Strings are quite a mess in Java, because they *behave* like primitive types (more on that later), but they really *are* classes. Also, you can just initialize a string using quotes `""` instead of having to call `new String()`, which makes them behave differently than *any other class* in the language. This complication is also the reason that you can't just compare two strings using `==`, but you have to use `.equals()` instead. Meh.
|
||||
|
||||
## Pass-by-reference vs. pass-by-value
|
||||
An important thing to know about primitive types compared to objects is the behavior they show when being passed into a method that accepts parameters. Let's look at the following code as an example:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
int i = 10;
|
||||
addOne(i);
|
||||
System.out.println(i); // still 10, what gives?
|
||||
}
|
||||
|
||||
private static void addOne(int i){
|
||||
i++;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the `addOne` method adds one to the parameter passed into it. But despite that, the code in our `main` method still prints out the number 10. This happens because primitive types (and `String`, hurr durr) use what is called *pass-by-value*: When calling `addOne`, its `i` variable is just set to the *value* of the `i` variable from our `main` method. It doesn't know about the actual *variable* we pass in, just its *value*.
|
||||
|
||||
This behavior, however, is different when using Objects. Let's rewrite the code above to use a custom class that contains an `int` field:
|
||||
```java
|
||||
// Thing.java
|
||||
public class Thing {
|
||||
public int i;
|
||||
public Thing(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Main.java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Thing thing = new Thing(10);
|
||||
addOne(thing);
|
||||
System.out.println(thing.i); // 11
|
||||
}
|
||||
|
||||
private static void addOne(Thing thing) {
|
||||
thing.i++;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the program now prints out 11 instead of 10. That's because of something Java uses called *pointers*[^1]. Our `thing` variable in the `main` method doesn't really store the actual *instance*, but instead, it stores the location of that instance in memory. So when passing that variable into the `addOne` method, all we pass is the information "The thing we're trying to modify sits in this part of memory, so modify the data there, please." That's why, when we then change the `Thing`'s `i` variable, it's also modified outside of the method.
|
||||
|
||||
# `null`
|
||||
Any variables that can store objects rather than primitive types (our `thing` variable from before, for example) can have a state where they don't point to an object, but instead, point to nothing. This "nothing" is called `null`.
|
||||
```java
|
||||
Thing noThing = null;
|
||||
```
|
||||
Using `null` can be useful in a lot of cases; however, it can also be quite dangerous: Trying to call a method or interact with a field of a variable that is `null` causes the program to crash:
|
||||
```java
|
||||
Thing noThing = null;
|
||||
System.out.println(noThing.i); // crashes
|
||||
```
|
||||
Just like any other objects, you can use `null` in comparisons:
|
||||
```java
|
||||
if (noThing == null) {
|
||||
System.out.println("I don't have a thing!");
|
||||
}
|
||||
```
|
||||
|
||||
# Arrays and Lists
|
||||
Arrays and Lists are two data types that you'll be using a lot of, because they're super useful. Their names kind of already give away what they do, but in case they don't mean anything to you: Arrays and lists are two ways to store multiple pieces of data easily without having to manage each piece on its own. This can be useful for stuff like *students in a classroom*, where you won't really know for certain beforehand how many students will be there at any given day. The difference between Arrays and Lists is that the former has a *fixed size*, while the latter has a *dynamic size*.
|
||||
|
||||
## Arrays
|
||||
Let's take a look at arrays first. An array has a fixed type, meaning that the objects in it can only be of the type you specify when creating the array. The variable type of an array of strings, for example, is written as `String[]`. To initialize an array, you have two options: Either you create an empty array based on a fixed size (where every slot will contain `null` to start with), or you create an array that already has stuff in it:
|
||||
```java
|
||||
int[] numbers = new int[10]; // empty array with 10 slots
|
||||
String[] names = new String[]{"Justus", "Peter", "Bob"};
|
||||
```
|
||||
You can query and modify the data in an array using array brackets `[]` like so:
|
||||
```java
|
||||
String justus = names[0]; // get the 0th entry
|
||||
names[1] = "Peter Shaw"; // modify the 1st entry
|
||||
```
|
||||
Note that, in Java, the first slot in an array has an index of 0, which means that the last slot of an array always has the index `length-1`. Every array has a `length` field which stores the amount of slots an array has, meaning you can query the length of `numbers` by writing `numbers.length`.
|
||||
|
||||
## Lists
|
||||
Lists[^2] work much in the same way, with the main difference being the way you identify them. Lists use something called *generic types*[^3] to allow you to also give them a fixed type. The variable type of a list of strings, for example, is written as `ArrayList<String>`, using angle brackets `<>` (which are really just "greater than" and "less than" signs). To create a list, simply call its constructor using `new`:
|
||||
```java
|
||||
ArrayList<Integer> numbers = new ArrayList<>();
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
```
|
||||
Note that, to create a list containing a primitive type, you need to specify its *wrapper class* instead of the native type itself[^4]. The wrapper class for `int` is `Integer`, and the wrapper classes for the other types are just their names with an uppercase first letter (`Boolean`, for example).
|
||||
|
||||
Also note that, when copying or writing this code in your IDE, it will automatically add `import` statements to the top of the class. All they do is make classes from other locations available to the current class, but you don't have to worry about them too much.
|
||||
|
||||
You can query and modify the data in a list using the methods from the `ArrayList` class:
|
||||
```java
|
||||
names.add("Justus"); // add entries
|
||||
names.add("Peter");
|
||||
names.add("Bob");
|
||||
|
||||
String justus = names.get(0); // get the 0th entry
|
||||
names.set(1, "Peter Shaw"); // modify the 1st entry
|
||||
|
||||
// the length of a list can be read using the size() method
|
||||
int length = names.size();
|
||||
```
|
||||
|
||||
Note that, when trying to access an index of a list or an array that is either less than 0 or greater than or equal to its length, your program will crash, so be careful.
|
||||
|
||||
# Conclusion
|
||||
So today, you learned some additional useful things about Java that I didn't really get a chance to mention at an earlier point. So let's write some code that makes use of them! If you want, you can try to solve the following problem, which is an extension of the problem from the previous tutorial:
|
||||
|
||||
> Let's imagine you're managing a small car dealership. You want to have a way of managing all of the cars you have in stock. This includes keeping track of their brand names, their horsepower, their license plate texts and their mileage. Currently, you have 15 parking spots for cars you can sell, 4 of which are already occupied with cars. Additionally, you keep track of a list of all the customers you have had so far (namely, you store their first and last names as well as the city they live in). At the current time, you've already had 3 customers. Additionally, you want to have a way of adding a new car to the first available parking spot, as well as a way to store the data of a new customer easily.
|
||||
|
||||
If you're stuck, you can [get some hints](https://gist.github.com/Ellpeck/3bdc69845d0d4c0e9511511dd06cfdc1) or [look at my solution](https://gist.github.com/Ellpeck/595b929ce666fca6fb0ed792ca98d71e).
|
||||
|
||||
Happy coding!
|
||||
|
||||
***
|
||||
|
||||
[^1]: Java's pointers work a lot differently from pointers in lower-level languages like C, because they're implicit: You don't create or manage them yourself. They're still called pointers though, so yea.
|
||||
|
||||
[^2]: Java has multiple types of lists (including, but not limited to `ArrayList` and `LinkedList`), but for the purpose of this tutorial, we'll only be looking at `ArrayList` since it's the most commonly used one and it also goes hand in hand with arrays.
|
||||
|
||||
[^3]: More on those in a later tutorial, probably. They're pretty useful.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 5: Things I Left Out So Far"
|
||||
description: In this Java tutorial for beginners, we cover some shorthands, some more data types, the difference between pass-by-reference and pass-by-value, null, as well as arrays and lists.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1184894859133509632
|
||||
---
|
||||
|
||||
After that complicated stuff we did in the last tutorial, how about we take it down a notch in this one and talk about some additional things that I haven't mentioned this far, but that will still be very useful to you as a programmer. Most of these things won't really have much connection to each other, but I'll give you an example at the end of this tutorial that combines some of them into a single use case.
|
||||
|
||||
# Shorthands
|
||||
Java has some shorthands to make addition and other mathematical operations faster. As there isn't really that much to explain (they're really just vocabulary), here's a list of them:
|
||||
```java
|
||||
// These two statements are equivalent
|
||||
// (This also works with all other math operators)
|
||||
i = i + 2;
|
||||
i += 2;
|
||||
|
||||
// When adding or subtracting 1, you can just do this:
|
||||
i++;
|
||||
i--;
|
||||
```
|
||||
|
||||
# Primitive Types
|
||||
Primitive types (also called *native types*) are variable types in a language that are baked into the very foundation of the language. That means they don't derive from a class, but they just exist as part of the language itself. The two primitive types you already know are `int` (32 bit integers) and `boolean` (`true` and `false`). In Java, primitive types always start with a lowercase letter (instead of an uppercase letter for classes).
|
||||
|
||||
Along with `int` and `boolean`, there are some more primitive types that could come in useful when programming. Here are the ones I haven't mentioned yet, quickly summed up:
|
||||
```java
|
||||
// "char" represents a single character.
|
||||
// Characters use single quotes ' rather than double quotes " (which are reserved for strings).
|
||||
char character = 'A';
|
||||
char fourthChar = "Hello World".charAt(4); // o
|
||||
|
||||
// "double" represents a 64bit floating point number
|
||||
// which is a number with a decimal point
|
||||
// It's called a double because it has double the precision of float (see below)
|
||||
double d = 3.14;
|
||||
|
||||
// "float" represents a 32bit floating point number (less precise than double).
|
||||
// To differentiate floats from doubles and ints, you have to append an "F".
|
||||
float f = 12.5F;
|
||||
|
||||
// "long" represents a 64bit integer (which can store a lot higher numbers than int)
|
||||
// To differentiate longs from ints, you have to append an "L".
|
||||
long l = 9223372036854775807L;
|
||||
|
||||
// "short" represents a 16bit integer
|
||||
short s = 32767;
|
||||
|
||||
// "byte" represents an 8bit integer
|
||||
byte b = 127;
|
||||
```
|
||||
|
||||
## What about `String`?
|
||||
Oh boy. Strings are quite a mess in Java, because they *behave* like primitive types (more on that later), but they really *are* classes. Also, you can just initialize a string using quotes `""` instead of having to call `new String()`, which makes them behave differently than *any other class* in the language. This complication is also the reason that you can't just compare two strings using `==`, but you have to use `.equals()` instead. Meh.
|
||||
|
||||
## Pass-by-reference vs. pass-by-value
|
||||
An important thing to know about primitive types compared to objects is the behavior they show when being passed into a method that accepts parameters. Let's look at the following code as an example:
|
||||
```java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
int i = 10;
|
||||
addOne(i);
|
||||
System.out.println(i); // still 10, what gives?
|
||||
}
|
||||
|
||||
private static void addOne(int i){
|
||||
i++;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the `addOne` method adds one to the parameter passed into it. But despite that, the code in our `main` method still prints out the number 10. This happens because primitive types (and `String`, hurr durr) use what is called *pass-by-value*: When calling `addOne`, its `i` variable is just set to the *value* of the `i` variable from our `main` method. It doesn't know about the actual *variable* we pass in, just its *value*.
|
||||
|
||||
This behavior, however, is different when using Objects. Let's rewrite the code above to use a custom class that contains an `int` field:
|
||||
```java
|
||||
// Thing.java
|
||||
public class Thing {
|
||||
public int i;
|
||||
public Thing(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Main.java
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Thing thing = new Thing(10);
|
||||
addOne(thing);
|
||||
System.out.println(thing.i); // 11
|
||||
}
|
||||
|
||||
private static void addOne(Thing thing) {
|
||||
thing.i++;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the program now prints out 11 instead of 10. That's because of something Java uses called *pointers*[^1]. Our `thing` variable in the `main` method doesn't really store the actual *instance*, but instead, it stores the location of that instance in memory. So when passing that variable into the `addOne` method, all we pass is the information "The thing we're trying to modify sits in this part of memory, so modify the data there, please." That's why, when we then change the `Thing`'s `i` variable, it's also modified outside of the method.
|
||||
|
||||
# `null`
|
||||
Any variables that can store objects rather than primitive types (our `thing` variable from before, for example) can have a state where they don't point to an object, but instead, point to nothing. This "nothing" is called `null`.
|
||||
```java
|
||||
Thing noThing = null;
|
||||
```
|
||||
Using `null` can be useful in a lot of cases; however, it can also be quite dangerous: Trying to call a method or interact with a field of a variable that is `null` causes the program to crash:
|
||||
```java
|
||||
Thing noThing = null;
|
||||
System.out.println(noThing.i); // crashes
|
||||
```
|
||||
Just like any other objects, you can use `null` in comparisons:
|
||||
```java
|
||||
if (noThing == null) {
|
||||
System.out.println("I don't have a thing!");
|
||||
}
|
||||
```
|
||||
|
||||
# Arrays and Lists
|
||||
Arrays and Lists are two data types that you'll be using a lot of, because they're super useful. Their names kind of already give away what they do, but in case they don't mean anything to you: Arrays and lists are two ways to store multiple pieces of data easily without having to manage each piece on its own. This can be useful for stuff like *students in a classroom*, where you won't really know for certain beforehand how many students will be there at any given day. The difference between Arrays and Lists is that the former has a *fixed size*, while the latter has a *dynamic size*.
|
||||
|
||||
## Arrays
|
||||
Let's take a look at arrays first. An array has a fixed type, meaning that the objects in it can only be of the type you specify when creating the array. The variable type of an array of strings, for example, is written as `String[]`. To initialize an array, you have two options: Either you create an empty array based on a fixed size (where every slot will contain `null` to start with), or you create an array that already has stuff in it:
|
||||
```java
|
||||
int[] numbers = new int[10]; // empty array with 10 slots
|
||||
String[] names = new String[]{"Justus", "Peter", "Bob"};
|
||||
```
|
||||
You can query and modify the data in an array using array brackets `[]` like so:
|
||||
```java
|
||||
String justus = names[0]; // get the 0th entry
|
||||
names[1] = "Peter Shaw"; // modify the 1st entry
|
||||
```
|
||||
Note that, in Java, the first slot in an array has an index of 0, which means that the last slot of an array always has the index `length-1`. Every array has a `length` field which stores the amount of slots an array has, meaning you can query the length of `numbers` by writing `numbers.length`.
|
||||
|
||||
## Lists
|
||||
Lists[^2] work much in the same way, with the main difference being the way you identify them. Lists use something called *generic types*[^3] to allow you to also give them a fixed type. The variable type of a list of strings, for example, is written as `ArrayList<String>`, using angle brackets `<>` (which are really just "greater than" and "less than" signs). To create a list, simply call its constructor using `new`:
|
||||
```java
|
||||
ArrayList<Integer> numbers = new ArrayList<>();
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
```
|
||||
Note that, to create a list containing a primitive type, you need to specify its *wrapper class* instead of the native type itself[^4]. The wrapper class for `int` is `Integer`, and the wrapper classes for the other types are just their names with an uppercase first letter (`Boolean`, for example).
|
||||
|
||||
Also note that, when copying or writing this code in your IDE, it will automatically add `import` statements to the top of the class. All they do is make classes from other locations available to the current class, but you don't have to worry about them too much.
|
||||
|
||||
You can query and modify the data in a list using the methods from the `ArrayList` class:
|
||||
```java
|
||||
names.add("Justus"); // add entries
|
||||
names.add("Peter");
|
||||
names.add("Bob");
|
||||
|
||||
String justus = names.get(0); // get the 0th entry
|
||||
names.set(1, "Peter Shaw"); // modify the 1st entry
|
||||
|
||||
// the length of a list can be read using the size() method
|
||||
int length = names.size();
|
||||
```
|
||||
|
||||
Note that, when trying to access an index of a list or an array that is either less than 0 or greater than or equal to its length, your program will crash, so be careful.
|
||||
|
||||
# Conclusion
|
||||
So today, you learned some additional useful things about Java that I didn't really get a chance to mention at an earlier point. So let's write some code that makes use of them! If you want, you can try to solve the following problem, which is an extension of the problem from the previous tutorial:
|
||||
|
||||
> Let's imagine you're managing a small car dealership. You want to have a way of managing all of the cars you have in stock. This includes keeping track of their brand names, their horsepower, their license plate texts and their mileage. Currently, you have 15 parking spots for cars you can sell, 4 of which are already occupied with cars. Additionally, you keep track of a list of all the customers you have had so far (namely, you store their first and last names as well as the city they live in). At the current time, you've already had 3 customers. Additionally, you want to have a way of adding a new car to the first available parking spot, as well as a way to store the data of a new customer easily.
|
||||
|
||||
If you're stuck, you can [get some hints](https://gist.github.com/Ellpeck/3bdc69845d0d4c0e9511511dd06cfdc1) or [look at my solution](https://gist.github.com/Ellpeck/595b929ce666fca6fb0ed792ca98d71e).
|
||||
|
||||
Happy coding!
|
||||
|
||||
***
|
||||
|
||||
[^1]: Java's pointers work a lot differently from pointers in lower-level languages like C, because they're implicit: You don't create or manage them yourself. They're still called pointers though, so yea.
|
||||
|
||||
[^2]: Java has multiple types of lists (including, but not limited to `ArrayList` and `LinkedList`), but for the purpose of this tutorial, we'll only be looking at `ArrayList` since it's the most commonly used one and it also goes hand in hand with arrays.
|
||||
|
||||
[^3]: More on those in a later tutorial, probably. They're pretty useful.
|
||||
|
||||
[^4]: Which is also just another annoying property of Java that could've been implemented a lot better (like in C#), but oh well, it is what it is.
|
|
@ -1,30 +1,30 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 😢 Lows
|
||||
summary: About depression and what it feels like when I don't know what to do with myself
|
||||
tags: [Miscellaneous]
|
||||
discuss: https://twitter.com/Ellpeck/status/1186028260838334471
|
||||
archived: true
|
||||
---
|
||||
|
||||
So some of you might be disappointed that this *isn't* the next Java tutorial. Well, today and the last couple of days, I haven't been feeling like working on those, because.. I've been depressed again. I never know how to describe it, or how to say it without seeming like it's just.. something I say when I'm too lazy to work on things.
|
||||
|
||||
This post will probably be a little all over the place, because that's also the mood that my head is currently in, but I'll try to explain to you what it feels like to me to have a low low follow a high high, mood-wise.
|
||||
|
||||
# Highs
|
||||
When I say that I'm depressed, it means something different than when I say that I'm suffering from depression. Because, for me, depression isn't a constant state. Before depression hits, I have long periods of highs, long periods of what non-depressed people would probably just call.. normal moods.
|
||||
|
||||
I get up in the mornings, I enjoy breakfast, I go to University, I do my daily chores, I sit down at my computer, I code, I play some games, and then I go to bed. Normal days, really.
|
||||
|
||||
And if you don't suffer from depression, then you might think "Well, what's so special about that?", and the annoying thing is: That's *exactly* what I also think when I'm experiencing a high. I take it for granted, and I never even stop to think about how great it is that I'm currently feeling normal about my life.
|
||||
|
||||
# Lows
|
||||
And then a low hits. And the longer the high has been going on for, the longer I was happy for, the harder it hits. Right now, I've been feeling low for two days, after a high that lasted almost *a month*. When I'm going through a low phase like now, my day works a lot differently.
|
||||
|
||||
I wake up at noon. I stay in bed. I check my phone. Hours pass. I think to myself "What am I doing?" I check my phone. After a while, I force myself to get up; I might even take a shower. I find some cookies in the back of my fridge; those'll be good enough for breakfast, I think to myself. I sit down at my computer. I watch some videos. "What am I doing?" Maybe some more videos. "What am I doing? I don't know what to do." I start Minecraft. "This sounds like fun!" I play for five minutes. I close the game again. "What am I doing?" I watch some videos. I start The Sims 4. I play for half an hour, and then I close the game again. "What am I doing?" I watch some more YouTube videos. I listen to some music. Should I do my coursework now? Not in the mood. I open IntelliJ. Let's work on some code. I glance at a couple of files, and then I close it again. "What am I doing?"
|
||||
|
||||
Take that whole description, and slow it down by about 200%. That's what a low day feels like to me. I feel like every single hour; every single *minute* even, is filled with doubt and emptiness and just... nothing.
|
||||
|
||||
This is so hard to explain for me because I also don't.. see myself in these low phases. I don't look at myself. I don't observe what I'm doing. It's like I'm not even there; it's like I'm not inside my own body, doing these activities with it. It's like it's just doing everything on some sort of weird auto-pilot mode.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 😢 Lows
|
||||
description: About depression and what it feels like when I don't know what to do with myself
|
||||
tags: [Miscellaneous]
|
||||
discuss: https://twitter.com/Ellpeck/status/1186028260838334471
|
||||
archived: true
|
||||
---
|
||||
|
||||
So some of you might be disappointed that this *isn't* the next Java tutorial. Well, today and the last couple of days, I haven't been feeling like working on those, because.. I've been depressed again. I never know how to describe it, or how to say it without seeming like it's just.. something I say when I'm too lazy to work on things.
|
||||
|
||||
This post will probably be a little all over the place, because that's also the mood that my head is currently in, but I'll try to explain to you what it feels like to me to have a low low follow a high high, mood-wise.
|
||||
|
||||
# Highs
|
||||
When I say that I'm depressed, it means something different than when I say that I'm suffering from depression. Because, for me, depression isn't a constant state. Before depression hits, I have long periods of highs, long periods of what non-depressed people would probably just call.. normal moods.
|
||||
|
||||
I get up in the mornings, I enjoy breakfast, I go to University, I do my daily chores, I sit down at my computer, I code, I play some games, and then I go to bed. Normal days, really.
|
||||
|
||||
And if you don't suffer from depression, then you might think "Well, what's so special about that?", and the annoying thing is: That's *exactly* what I also think when I'm experiencing a high. I take it for granted, and I never even stop to think about how great it is that I'm currently feeling normal about my life.
|
||||
|
||||
# Lows
|
||||
And then a low hits. And the longer the high has been going on for, the longer I was happy for, the harder it hits. Right now, I've been feeling low for two days, after a high that lasted almost *a month*. When I'm going through a low phase like now, my day works a lot differently.
|
||||
|
||||
I wake up at noon. I stay in bed. I check my phone. Hours pass. I think to myself "What am I doing?" I check my phone. After a while, I force myself to get up; I might even take a shower. I find some cookies in the back of my fridge; those'll be good enough for breakfast, I think to myself. I sit down at my computer. I watch some videos. "What am I doing?" Maybe some more videos. "What am I doing? I don't know what to do." I start Minecraft. "This sounds like fun!" I play for five minutes. I close the game again. "What am I doing?" I watch some videos. I start The Sims 4. I play for half an hour, and then I close the game again. "What am I doing?" I watch some more YouTube videos. I listen to some music. Should I do my coursework now? Not in the mood. I open IntelliJ. Let's work on some code. I glance at a couple of files, and then I close it again. "What am I doing?"
|
||||
|
||||
Take that whole description, and slow it down by about 200%. That's what a low day feels like to me. I feel like every single hour; every single *minute* even, is filled with doubt and emptiness and just... nothing.
|
||||
|
||||
This is so hard to explain for me because I also don't.. see myself in these low phases. I don't look at myself. I don't observe what I'm doing. It's like I'm not even there; it's like I'm not inside my own body, doing these activities with it. It's like it's just doing everything on some sort of weird auto-pilot mode.
|
||||
|
||||
So until that passes, I probably won't be working on any tutorials, or anything, really. Let's hope it passes fairly soon, because I'm honestly sick of forcing myself to eat cookies for breakfast. It might sound great, but eating something when you have absolutely no desire to eat things is... quite unpleasant, really.
|
|
@ -1,159 +1,159 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 6: Inheritance"
|
||||
summary: In this Java tutorial for beginners, we cover classes extending other classes and the instanceof keyword.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1189904487722487809
|
||||
---
|
||||
|
||||
For this tutorial, let's expand on the car dealership example from the end of the last tutorial: You have a car dealership, and you want to expand it to sell various other types of motor vehicles; let's say... motorbikes and trucks as well. Obviously, these different kinds of vehicles all have different properties: A motorbike requires the use of a helmet, and an important piece of information about a truck might be how big its storage area is.
|
||||
|
||||
Now, this is where object-oriented languages like Java shine.
|
||||
|
||||
# Extending Other Classes
|
||||
The concept of extending other classes is probably best explained with an example, so to start out with, let's create a class that represents a car with a certain amount of wheels:
|
||||
```java
|
||||
public class Car {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Car(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, this is just a simple class with a variable that can store how many wheels a vehicle has.
|
||||
|
||||
Now, let's imagine we want to create a class that represents a truck, and we would want any truck to store information on how many wheels it has, as well as how many cubic meters of storage it has available:
|
||||
```java
|
||||
public class Truck {
|
||||
public int amountOfWheels;
|
||||
public int storageArea;
|
||||
|
||||
public Truck(int amountOfWheels, int storageArea) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, just creating the class like usual isn't really that pretty, because now both our `Car` class and our `Truck` class have separate `amountOfWheels` fields, despite the fact that they really refer to the same thing: The amount of wheels of a vehicle.
|
||||
|
||||
What we'd like to be able to do instead is to have the amount of wheels stored in a different location that both our `Truck` and our `Car` class can access. The first step of achieving this is creating another class that only stores information both of our vehicles should have:
|
||||
```java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Vehicle(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
}
|
||||
```
|
||||
Now, we can use the `extends` keyword that Java provides to cause both of our other classes to also have access to this information. Let's modify our `Car` class first and I'll explain afterwards what exactly our modification will do.
|
||||
```java
|
||||
public class Car extends Vehicle {
|
||||
public Car(int amountOfWheels) {
|
||||
// Note that the line below will be explained in a bit
|
||||
super(amountOfWheels);
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, our `Car` class now `extends Vehicle`. This means that the `Car` class is basically just an *upgraded* version of the `Vehicle` class: It contains all of the information that the `Vehicle` class provides (including fields and methods), but it can also provide its own additional information. From the perspective of `Car`, `Vehicle` is the *superclass*, and from the perspective of `Vehicle`, `Car` is a *child class*.
|
||||
|
||||
It should be noted that any class can only extend *one* other class, so `Car` couldn't extend both `Vehicle` and, let's say, `FueledDevice`. However, the other way around is possible: `Vehicle` can be extended by multiple classes, meaning that we can modify our `Truck` class to also be a child class like this:
|
||||
```java
|
||||
public class Truck extends Vehicle {
|
||||
public int storageArea;
|
||||
|
||||
public Truck(int amountOfWheels, int storageArea) {
|
||||
super(amountOfWheels);
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the `Truck` class now uses the `amountOfWheels` field from its superclass, but it defines its own `storageArea` field that only trucks have.
|
||||
|
||||
## `super`
|
||||
Now, you've probably been wondering what line 5 means: `super(amountOfWheels)`. As we defined earlier, our `Vehicle` class takes one argument in its constructor: The amount of wheels that it has. As we also previously discussed, a constructor *has to be called* when a new object is created. So, when creating a `Truck` object, the `Truck` constructor is called, but, in turn, it needs to also implicitly call the `Vehicle` constructor.
|
||||
|
||||
When placing a `super()` call at the start of the constructor of a class, the constructor of the class that is being extended will be called. If that class takes a set of arguments in its constructor, we have to pass it those arguments, similarly to if we were creating an object of that class.
|
||||
|
||||
That's what our `super(amountOfWheels)` is doing here: It's calling the constructor of `Vehicle` with the `amountOfWheels` argument.
|
||||
|
||||
It should be noted that we don't *necessarily* have to pass a variable into the super constructor. For instance, we know for a fact that a truck will always have four wheels, so we can modify our `Truck` constructor to always specify 4 as the wheel amount given to the superclass:
|
||||
```java
|
||||
public Truck(int storageArea) {
|
||||
super(4);
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
```
|
||||
|
||||
## The `Object` class
|
||||
It should be noted at this point that *all classes* extend the `Object` class implicitly (meaning you never have to write `extends Object` anywhere and it will still hold true). This will be useful pretty soon.
|
||||
|
||||
## About Variable Types
|
||||
Let's imagine we want to store the stock that we sell at our dealership, without specifying separate lists for the different kinds of vehicles we're selling. What we can do is have that variable be of type `Vehicle`, which will automatically allow instances of child classes to be stored in the variable (or list) like so:
|
||||
```java
|
||||
ArrayList<Vehicle> stock = new ArrayList<>();
|
||||
stock.add(new Car(4));
|
||||
stock.add(new Truck(10));
|
||||
|
||||
// or in the case of variables
|
||||
Vehicle car = new Car(4);
|
||||
Vehicle truck = new Truck(10);
|
||||
```
|
||||
|
||||
# `instanceof` and Type Casting
|
||||
Staying with our list of the stock we have, let's imagine we want to find all of the *trucks* that we have in stock, disregarding any other kinds of vehicles that we might have.
|
||||
|
||||
This is what the `instanceof` keyword can be used for: Using it, you can ask any object if it derives of a certain class; that is, if any object is an instance of the specified class.
|
||||
|
||||
Let's create a method to return a list of all of the cars we have in stock:
|
||||
```java
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
private static ArrayList<Vehicle> stock = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
stock.add(new Car(4));
|
||||
stock.add(new Truck(10));
|
||||
getTrucks();
|
||||
}
|
||||
|
||||
private static void getTrucks() {
|
||||
for (int i = 0; i < stock.size(); i++) {
|
||||
Vehicle vehicle = stock.get(i);
|
||||
if (vehicle instanceof Truck) {
|
||||
System.out.println("Vehicle " + i + " is a truck!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I've expanded the code from before to have a `getTrucks` method, which iterates through every vehicle we have in stock and if it finds a vehicle that is an instance of the `Truck` class, it will print out a message.
|
||||
|
||||
Another way to think about the `instanceof` keyword is as a weird, clunky synonym to the word "is": When asking `vehicle instanceof Truck`, we're really asking "Is this vehicle a truck?"
|
||||
|
||||
Now that we know which of the vehicles we have in stock are trucks, it might also be useful to know the storage capabilities of all of those trucks. However, as you can see, the `i`th vehicle we're currently inspecting is always of typ `Vehicle`, as that's what we store in the `stock` list. That means that we won't be able to access any `Truck`'s `storageArea` variable. That's what the concept of *type casting* can be used for.
|
||||
|
||||
If you have a variable of a certain type, but you know for a fact that it's actually an instance of a *child class* of that type, then you can change that variable to be of the child class' type instead like so:
|
||||
```java
|
||||
Vehicle vehicle = stock.get(i);
|
||||
if (vehicle instanceof Truck) {
|
||||
Truck truck = (Truck) vehicle;
|
||||
System.out.println("The " + i + "th truck can store " + truck.storageArea);
|
||||
}
|
||||
```
|
||||
As you can see, to type cast a variable into a different type, all you have to do is write that type in parentheses `()` in front of the variable.[^1] Cool.
|
||||
|
||||
# Conclusion
|
||||
So today, you learned one of the important aspects of object oriented programming, which is very useful in a heap of different scenarios, as you will be able to see throughout the next tutorials. Next time, we'll be covering overriding methods from superclasses, which will allow you to do even more cool stuff with inheritance.[^2]
|
||||
|
||||
I'm sorry that I've been taking such a long break from the tutorials, but after asking on Twitter if you people actually learn from them, a lot of you said that you do, and so that gave me the motivation to continue working on these.
|
||||
|
||||
So thanks a lot, and happy coding! <3
|
||||
|
||||
***
|
||||
|
||||
[^1]: As you might be able to see now, this concept is called type *casting* because it's like we're putting the vehicle into a mold (or a *cast*) to reshape it into a different type.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 6: Inheritance"
|
||||
description: In this Java tutorial for beginners, we cover classes extending other classes and the instanceof keyword.
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1189904487722487809
|
||||
---
|
||||
|
||||
For this tutorial, let's expand on the car dealership example from the end of the last tutorial: You have a car dealership, and you want to expand it to sell various other types of motor vehicles; let's say... motorbikes and trucks as well. Obviously, these different kinds of vehicles all have different properties: A motorbike requires the use of a helmet, and an important piece of information about a truck might be how big its storage area is.
|
||||
|
||||
Now, this is where object-oriented languages like Java shine.
|
||||
|
||||
# Extending Other Classes
|
||||
The concept of extending other classes is probably best explained with an example, so to start out with, let's create a class that represents a car with a certain amount of wheels:
|
||||
```java
|
||||
public class Car {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Car(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, this is just a simple class with a variable that can store how many wheels a vehicle has.
|
||||
|
||||
Now, let's imagine we want to create a class that represents a truck, and we would want any truck to store information on how many wheels it has, as well as how many cubic meters of storage it has available:
|
||||
```java
|
||||
public class Truck {
|
||||
public int amountOfWheels;
|
||||
public int storageArea;
|
||||
|
||||
public Truck(int amountOfWheels, int storageArea) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, just creating the class like usual isn't really that pretty, because now both our `Car` class and our `Truck` class have separate `amountOfWheels` fields, despite the fact that they really refer to the same thing: The amount of wheels of a vehicle.
|
||||
|
||||
What we'd like to be able to do instead is to have the amount of wheels stored in a different location that both our `Truck` and our `Car` class can access. The first step of achieving this is creating another class that only stores information both of our vehicles should have:
|
||||
```java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Vehicle(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
}
|
||||
```
|
||||
Now, we can use the `extends` keyword that Java provides to cause both of our other classes to also have access to this information. Let's modify our `Car` class first and I'll explain afterwards what exactly our modification will do.
|
||||
```java
|
||||
public class Car extends Vehicle {
|
||||
public Car(int amountOfWheels) {
|
||||
// Note that the line below will be explained in a bit
|
||||
super(amountOfWheels);
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, our `Car` class now `extends Vehicle`. This means that the `Car` class is basically just an *upgraded* version of the `Vehicle` class: It contains all of the information that the `Vehicle` class provides (including fields and methods), but it can also provide its own additional information. From the perspective of `Car`, `Vehicle` is the *superclass*, and from the perspective of `Vehicle`, `Car` is a *child class*.
|
||||
|
||||
It should be noted that any class can only extend *one* other class, so `Car` couldn't extend both `Vehicle` and, let's say, `FueledDevice`. However, the other way around is possible: `Vehicle` can be extended by multiple classes, meaning that we can modify our `Truck` class to also be a child class like this:
|
||||
```java
|
||||
public class Truck extends Vehicle {
|
||||
public int storageArea;
|
||||
|
||||
public Truck(int amountOfWheels, int storageArea) {
|
||||
super(amountOfWheels);
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, the `Truck` class now uses the `amountOfWheels` field from its superclass, but it defines its own `storageArea` field that only trucks have.
|
||||
|
||||
## `super`
|
||||
Now, you've probably been wondering what line 5 means: `super(amountOfWheels)`. As we defined earlier, our `Vehicle` class takes one argument in its constructor: The amount of wheels that it has. As we also previously discussed, a constructor *has to be called* when a new object is created. So, when creating a `Truck` object, the `Truck` constructor is called, but, in turn, it needs to also implicitly call the `Vehicle` constructor.
|
||||
|
||||
When placing a `super()` call at the start of the constructor of a class, the constructor of the class that is being extended will be called. If that class takes a set of arguments in its constructor, we have to pass it those arguments, similarly to if we were creating an object of that class.
|
||||
|
||||
That's what our `super(amountOfWheels)` is doing here: It's calling the constructor of `Vehicle` with the `amountOfWheels` argument.
|
||||
|
||||
It should be noted that we don't *necessarily* have to pass a variable into the super constructor. For instance, we know for a fact that a truck will always have four wheels, so we can modify our `Truck` constructor to always specify 4 as the wheel amount given to the superclass:
|
||||
```java
|
||||
public Truck(int storageArea) {
|
||||
super(4);
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
```
|
||||
|
||||
## The `Object` class
|
||||
It should be noted at this point that *all classes* extend the `Object` class implicitly (meaning you never have to write `extends Object` anywhere and it will still hold true). This will be useful pretty soon.
|
||||
|
||||
## About Variable Types
|
||||
Let's imagine we want to store the stock that we sell at our dealership, without specifying separate lists for the different kinds of vehicles we're selling. What we can do is have that variable be of type `Vehicle`, which will automatically allow instances of child classes to be stored in the variable (or list) like so:
|
||||
```java
|
||||
ArrayList<Vehicle> stock = new ArrayList<>();
|
||||
stock.add(new Car(4));
|
||||
stock.add(new Truck(10));
|
||||
|
||||
// or in the case of variables
|
||||
Vehicle car = new Car(4);
|
||||
Vehicle truck = new Truck(10);
|
||||
```
|
||||
|
||||
# `instanceof` and Type Casting
|
||||
Staying with our list of the stock we have, let's imagine we want to find all of the *trucks* that we have in stock, disregarding any other kinds of vehicles that we might have.
|
||||
|
||||
This is what the `instanceof` keyword can be used for: Using it, you can ask any object if it derives of a certain class; that is, if any object is an instance of the specified class.
|
||||
|
||||
Let's create a method to return a list of all of the cars we have in stock:
|
||||
```java
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
private static ArrayList<Vehicle> stock = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
stock.add(new Car(4));
|
||||
stock.add(new Truck(10));
|
||||
getTrucks();
|
||||
}
|
||||
|
||||
private static void getTrucks() {
|
||||
for (int i = 0; i < stock.size(); i++) {
|
||||
Vehicle vehicle = stock.get(i);
|
||||
if (vehicle instanceof Truck) {
|
||||
System.out.println("Vehicle " + i + " is a truck!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I've expanded the code from before to have a `getTrucks` method, which iterates through every vehicle we have in stock and if it finds a vehicle that is an instance of the `Truck` class, it will print out a message.
|
||||
|
||||
Another way to think about the `instanceof` keyword is as a weird, clunky synonym to the word "is": When asking `vehicle instanceof Truck`, we're really asking "Is this vehicle a truck?"
|
||||
|
||||
Now that we know which of the vehicles we have in stock are trucks, it might also be useful to know the storage capabilities of all of those trucks. However, as you can see, the `i`th vehicle we're currently inspecting is always of typ `Vehicle`, as that's what we store in the `stock` list. That means that we won't be able to access any `Truck`'s `storageArea` variable. That's what the concept of *type casting* can be used for.
|
||||
|
||||
If you have a variable of a certain type, but you know for a fact that it's actually an instance of a *child class* of that type, then you can change that variable to be of the child class' type instead like so:
|
||||
```java
|
||||
Vehicle vehicle = stock.get(i);
|
||||
if (vehicle instanceof Truck) {
|
||||
Truck truck = (Truck) vehicle;
|
||||
System.out.println("The " + i + "th truck can store " + truck.storageArea);
|
||||
}
|
||||
```
|
||||
As you can see, to type cast a variable into a different type, all you have to do is write that type in parentheses `()` in front of the variable.[^1] Cool.
|
||||
|
||||
# Conclusion
|
||||
So today, you learned one of the important aspects of object oriented programming, which is very useful in a heap of different scenarios, as you will be able to see throughout the next tutorials. Next time, we'll be covering overriding methods from superclasses, which will allow you to do even more cool stuff with inheritance.[^2]
|
||||
|
||||
I'm sorry that I've been taking such a long break from the tutorials, but after asking on Twitter if you people actually learn from them, a lot of you said that you do, and so that gave me the motivation to continue working on these.
|
||||
|
||||
So thanks a lot, and happy coding! <3
|
||||
|
||||
***
|
||||
|
||||
[^1]: As you might be able to see now, this concept is called type *casting* because it's like we're putting the vehicle into a mold (or a *cast*) to reshape it into a different type.
|
||||
|
||||
[^2]: I was originally planning on including that in this tutorial already, but I noticed that that might be a bit too much after all, so I'll be doing it next time instead.
|
|
@ -1,235 +1,235 @@
|
|||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 7: Overriding Methods"
|
||||
summary: In this Java tutorial for beginners, we cover overriding methods, calling superclass methods and toString().
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1199339701640945664
|
||||
---
|
||||
|
||||
So it's been a hot minute since the last tutorial, and I apologize for that. However, it seems like there are some people that actually use these tutorials to properly learn Java, and so I didn't want to leave you all hanging.
|
||||
|
||||
Today's tutorial is going to cover method overrides, which are another awesome object orientation concept that will help you out greatly when programming.
|
||||
|
||||
Let's imagine that we want our different vehicle types (`Car` and `Truck`) from the last tutorial to be able to print out some information about themselves to the console. To do so, we could simply add a `printInformation()` method to each of the classes. However, that would end up being problematic if we wanted to print out information about *the entirety of our stock*, which, as you might recall, is stored in our `ArrayList<Vehicle> stock`, as we would have to create `instanceof` checks for both `Car` and `Truck` to be able to access their `printInformation()` methods.
|
||||
|
||||
An easy fix for that would be to create a basic `printInformation()` method in our base class (`Vehicle`) and then *override* that method in our subclasses, allowing us to change their behavior. Let's see what that would look like:
|
||||
```java
|
||||
// Vehicle.java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Vehicle(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
|
||||
public void printInformation() {
|
||||
// Does nothing for now
|
||||
}
|
||||
}
|
||||
|
||||
// Car.java
|
||||
public class Car extends Vehicle {
|
||||
public Car(int amountOfWheels) {
|
||||
super(amountOfWheels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printInformation() {
|
||||
System.out.println("This car has " + this.amountOfWheels + " wheels");
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I've added a simple `printInformation()` method to the `Vehicle` class (which does absolutely nothing for now). However, I have then *overridden* that method in the `Car` class. The way I've done that is by adding a method that has the exact same name, return type and accepted parameters as the base class's method. Technically, that would already be enough to override a method, however, to make it a little clearer to read, people usually like to add the `@Override` annotation[^1] above the method.
|
||||
|
||||
So what does this mean, exactly? Basically, when calling the `printInformation()` method on an instance of the `Vehicle` class, nothing will happen, because the `Vehicle`'s method is empty. However, when calling the method on an instance of the `Car` class, the print statement above will be executed, printing information about the car's wheel amount.
|
||||
|
||||
The important thing to understand is this: Which class's method is called isn't determined by the *variable type*, but by the type that the object itself has. Let's check out this example:
|
||||
```java
|
||||
// This is in our Main class from last time
|
||||
private static void getTrucks() {
|
||||
for (int i = 0; i < stock.size(); i++) {
|
||||
Vehicle vehicle = stock.get(i);
|
||||
vehicle.printInformation();
|
||||
}
|
||||
}
|
||||
```
|
||||
Now, each vehicle that isn't a car (so each truck in ou example) will not print out any information, but each of our cars will print out the information we specified above, despite the fact that we're not doing any `instanceof` checks or anything else. Cool.
|
||||
|
||||
# Calling `super` methods
|
||||
Now, if we wanted to also add an override of the `printInformation()` method to our `Truck` class, we will come across a minor annoyance: To print out the truck's amount of wheels, we'd basically have to copy the print statement from our `Car` class, which is a bit ugly.
|
||||
|
||||
Well, that's where `super` calls come to the rescue! We've already briefly touched on super calls when talking about the super constructor for extending other classes, and super calls are very similar to that. Let's change our code up a bit, and then I'll explain what it all means.
|
||||
```java
|
||||
// Vehicle.java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Vehicle(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
|
||||
public void printInformation() {
|
||||
System.out.println("Vehicle info:");
|
||||
System.out.println("Wheel amount: " + this.amountOfWheels);
|
||||
}
|
||||
}
|
||||
|
||||
// Car.java
|
||||
public class Car extends Vehicle {
|
||||
public Car(int amountOfWheels) {
|
||||
super(amountOfWheels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printInformation() {
|
||||
super.printInformation();
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I've modified the `Vehicle`'s method to print out the wheel amount by default, and I've changed the `Car`'s method to call `super.printInformation()`. What this call does is simply execute its parent class's `printInformation()` method, so a car will also have its wheel amount printed out just the same as any other vehicle.
|
||||
|
||||
It should be noted that simply calling the `super` method in an override and doing absolutely nothing else is *the default behavior*, meaning that, in the example above, we could leave out the `printInformation()` override in our `Car` class completely and still get the same effect.
|
||||
|
||||
Now let's add a `printInformation()` override to our `Truck` class as well, but this time, let's extend the behavior a bit:
|
||||
```java
|
||||
public class Truck extends Vehicle {
|
||||
public int storageArea;
|
||||
|
||||
public Truck(int storageArea) {
|
||||
super(4);
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printInformation() {
|
||||
super.printInformation();
|
||||
System.out.println("Storage area: " + this.storageArea);
|
||||
}
|
||||
}
|
||||
```
|
||||
Now, calling a truck's `printInformation()` method will *first* print out "Vehicle information:", then the wheel amount, and then the storage area. If we wanted this behavior to occur in a different order, we could simply swap the two lines as follows:
|
||||
```java
|
||||
@Override
|
||||
public void printInformation() {
|
||||
System.out.println("Storage area: " + this.storageArea);
|
||||
super.printInformation();
|
||||
}
|
||||
```
|
||||
Now, the storage area will be printed out *first*, followed by "Vehicle information:" and the wheel amount.[^2]
|
||||
|
||||
# `Object` methods
|
||||
As I briefly mentioned in the last tutorial, *all* classes implicitly extend Java's `Object` class without you having to specify that information. This is finally going to be useful now, as this class provides some useful methods that we can override in our implementations.
|
||||
|
||||
## `toString()`
|
||||
This method is probably the most versatile one of the bunch: It gets called whenever an object's information needs to be converted into a string in some circumstance. For example, if you simply write
|
||||
```java
|
||||
Car car = new Car(4);
|
||||
System.out.println(car);
|
||||
```
|
||||
then the car's `toString()` method will be called inside of `println` in order to convert the car's information into a string.
|
||||
|
||||
However, by default, the `toString()` method simply prints out some not-so-useful information about the object's internal identifier. If we override this method, however, we can make it display some more useful information. Let's do so in our `Vehicle` and `Car` class as an example:
|
||||
```java
|
||||
// Vehicle.java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Vehicle(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Vehicle with " + this.amountOfWheels + " wheels";
|
||||
}
|
||||
}
|
||||
|
||||
// Truck.java
|
||||
public class Truck extends Vehicle {
|
||||
public int storageArea;
|
||||
|
||||
public Truck(int storageArea) {
|
||||
super(4);
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String vehicleInfo = super.toString();
|
||||
return vehicleInfo + " and " + this.storageArea + " storage area";
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, `Truck` additionally calls the `toString()` super method and then appends some more information to the string created in `Vehicle`. Pretty nice.
|
||||
|
||||
## `equals()`
|
||||
Remember how I told you that you should always use `equals()` to compare two strings instead of the double equals sign `==`?
|
||||
|
||||
Well, here's why: Java's `String` class overrides the `equals()` method from `Object` and changes its behavior so that two strings are considered equal if their contents are identical.
|
||||
|
||||
As an example, let's first override the `equals()` method in our `Vehicle` class with the default behavior that it would have if you didn't override it at all:
|
||||
```java
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return this == other;
|
||||
}
|
||||
```
|
||||
As you can see, the default behavior is simply the double equals sign `==`, which compares if two variable pointers point to the exact same object, as previously explained. That's not what we might want in our example, though.
|
||||
|
||||
Let's expand our `Vehicle` class to also have a unique identifier: The license plate's text. Let's say that we want to identify each vehicle by its plate, and so we make it the key factor in determining whether two vehicles are the same or not:
|
||||
```java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
public String licensePlate;
|
||||
|
||||
public Vehicle(int amountOfWheels, String licensePlate) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
this.licensePlate = licensePlate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof Vehicle) {
|
||||
Vehicle v = (Vehicle) other;
|
||||
return v.licensePlate.equals(this.licensePlate);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, each `Vehicle` now accepts a license plate in the constructor, and the `equals()` method is overridden in a way that makes two vehicles be considered equal if their license plates match exactly.
|
||||
|
||||
Now, a great example of how this could be useful is with lists. The `ArrayList` class contains the `contains()` method, which determines if a certain element is already present in the list. Now, the cool thing is that this method uses the `equals()` method on each element to determine whether or not an element is present. We can use this behavior to check if a vehicle with a certain license plate is already in our stock pretty easily:
|
||||
```java
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
private static ArrayList<Vehicle> stock = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
stock.add(new Car(4, "AC JS 1999"));
|
||||
stock.add(new Truck(10, "AC NS 1998"));
|
||||
|
||||
Car carToCheck = new Car(4, "AC HI 1234");
|
||||
if (stock.contains(carToCheck)) {
|
||||
System.out.println("The queried car is already in our stock :)");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Obviously, in this specific example, the text won't be printed because there isn't a car with that license plate in the `stock` list.
|
||||
|
||||
# Conclusion
|
||||
So yea, today you learned about the second key concept of object orientation in Java. To put this knowledge to the test, I'm going to give you an exercise all about extending classes and overriding methods that you can try to solve if you want.
|
||||
|
||||
> Let's imagine you're trying to create a program that allows you to draw manage different shapes, namely rectangles, right angle triangles and circles. Obviously, these shapes all have different properties, like the rectangle's and triangle's side lengths and the circle's radius. All of the shapes you currently have are stored in a list. For each of the shapes, you want to be able to calculate its circumference as well as its area. To test this program, you add a couple of shapes to your list and calculate the average of all of their areas and circumferences.
|
||||
|
||||
Note that you can find some methods and constants you might need in Java's default `Math` class, namely `Math.PI` and `Math.sqrt()`, the latter of which is used to calculate a square root. If you're stuck, you can [check my solution](https://gist.github.com/Ellpeck/8cf63c747313e070b7475d99e2bed5a1).
|
||||
|
||||
As always, happy coding!
|
||||
|
||||
***
|
||||
|
||||
[^1]: Annotations are another rather advanced topic that almost never comes up when using Java. They can be useful sometimes, but you'll hardly ever have a use for them.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: "☕ Java Tutorial, Part 7: Overriding Methods"
|
||||
description: In this Java tutorial for beginners, we cover overriding methods, calling superclass methods and toString().
|
||||
tags: [Java Tutorials]
|
||||
discuss: https://twitter.com/Ellpeck/status/1199339701640945664
|
||||
---
|
||||
|
||||
So it's been a hot minute since the last tutorial, and I apologize for that. However, it seems like there are some people that actually use these tutorials to properly learn Java, and so I didn't want to leave you all hanging.
|
||||
|
||||
Today's tutorial is going to cover method overrides, which are another awesome object orientation concept that will help you out greatly when programming.
|
||||
|
||||
Let's imagine that we want our different vehicle types (`Car` and `Truck`) from the last tutorial to be able to print out some information about themselves to the console. To do so, we could simply add a `printInformation()` method to each of the classes. However, that would end up being problematic if we wanted to print out information about *the entirety of our stock*, which, as you might recall, is stored in our `ArrayList<Vehicle> stock`, as we would have to create `instanceof` checks for both `Car` and `Truck` to be able to access their `printInformation()` methods.
|
||||
|
||||
An easy fix for that would be to create a basic `printInformation()` method in our base class (`Vehicle`) and then *override* that method in our subclasses, allowing us to change their behavior. Let's see what that would look like:
|
||||
```java
|
||||
// Vehicle.java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Vehicle(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
|
||||
public void printInformation() {
|
||||
// Does nothing for now
|
||||
}
|
||||
}
|
||||
|
||||
// Car.java
|
||||
public class Car extends Vehicle {
|
||||
public Car(int amountOfWheels) {
|
||||
super(amountOfWheels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printInformation() {
|
||||
System.out.println("This car has " + this.amountOfWheels + " wheels");
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I've added a simple `printInformation()` method to the `Vehicle` class (which does absolutely nothing for now). However, I have then *overridden* that method in the `Car` class. The way I've done that is by adding a method that has the exact same name, return type and accepted parameters as the base class's method. Technically, that would already be enough to override a method, however, to make it a little clearer to read, people usually like to add the `@Override` annotation[^1] above the method.
|
||||
|
||||
So what does this mean, exactly? Basically, when calling the `printInformation()` method on an instance of the `Vehicle` class, nothing will happen, because the `Vehicle`'s method is empty. However, when calling the method on an instance of the `Car` class, the print statement above will be executed, printing information about the car's wheel amount.
|
||||
|
||||
The important thing to understand is this: Which class's method is called isn't determined by the *variable type*, but by the type that the object itself has. Let's check out this example:
|
||||
```java
|
||||
// This is in our Main class from last time
|
||||
private static void getTrucks() {
|
||||
for (int i = 0; i < stock.size(); i++) {
|
||||
Vehicle vehicle = stock.get(i);
|
||||
vehicle.printInformation();
|
||||
}
|
||||
}
|
||||
```
|
||||
Now, each vehicle that isn't a car (so each truck in ou example) will not print out any information, but each of our cars will print out the information we specified above, despite the fact that we're not doing any `instanceof` checks or anything else. Cool.
|
||||
|
||||
# Calling `super` methods
|
||||
Now, if we wanted to also add an override of the `printInformation()` method to our `Truck` class, we will come across a minor annoyance: To print out the truck's amount of wheels, we'd basically have to copy the print statement from our `Car` class, which is a bit ugly.
|
||||
|
||||
Well, that's where `super` calls come to the rescue! We've already briefly touched on super calls when talking about the super constructor for extending other classes, and super calls are very similar to that. Let's change our code up a bit, and then I'll explain what it all means.
|
||||
```java
|
||||
// Vehicle.java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Vehicle(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
|
||||
public void printInformation() {
|
||||
System.out.println("Vehicle info:");
|
||||
System.out.println("Wheel amount: " + this.amountOfWheels);
|
||||
}
|
||||
}
|
||||
|
||||
// Car.java
|
||||
public class Car extends Vehicle {
|
||||
public Car(int amountOfWheels) {
|
||||
super(amountOfWheels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printInformation() {
|
||||
super.printInformation();
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, I've modified the `Vehicle`'s method to print out the wheel amount by default, and I've changed the `Car`'s method to call `super.printInformation()`. What this call does is simply execute its parent class's `printInformation()` method, so a car will also have its wheel amount printed out just the same as any other vehicle.
|
||||
|
||||
It should be noted that simply calling the `super` method in an override and doing absolutely nothing else is *the default behavior*, meaning that, in the example above, we could leave out the `printInformation()` override in our `Car` class completely and still get the same effect.
|
||||
|
||||
Now let's add a `printInformation()` override to our `Truck` class as well, but this time, let's extend the behavior a bit:
|
||||
```java
|
||||
public class Truck extends Vehicle {
|
||||
public int storageArea;
|
||||
|
||||
public Truck(int storageArea) {
|
||||
super(4);
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printInformation() {
|
||||
super.printInformation();
|
||||
System.out.println("Storage area: " + this.storageArea);
|
||||
}
|
||||
}
|
||||
```
|
||||
Now, calling a truck's `printInformation()` method will *first* print out "Vehicle information:", then the wheel amount, and then the storage area. If we wanted this behavior to occur in a different order, we could simply swap the two lines as follows:
|
||||
```java
|
||||
@Override
|
||||
public void printInformation() {
|
||||
System.out.println("Storage area: " + this.storageArea);
|
||||
super.printInformation();
|
||||
}
|
||||
```
|
||||
Now, the storage area will be printed out *first*, followed by "Vehicle information:" and the wheel amount.[^2]
|
||||
|
||||
# `Object` methods
|
||||
As I briefly mentioned in the last tutorial, *all* classes implicitly extend Java's `Object` class without you having to specify that information. This is finally going to be useful now, as this class provides some useful methods that we can override in our implementations.
|
||||
|
||||
## `toString()`
|
||||
This method is probably the most versatile one of the bunch: It gets called whenever an object's information needs to be converted into a string in some circumstance. For example, if you simply write
|
||||
```java
|
||||
Car car = new Car(4);
|
||||
System.out.println(car);
|
||||
```
|
||||
then the car's `toString()` method will be called inside of `println` in order to convert the car's information into a string.
|
||||
|
||||
However, by default, the `toString()` method simply prints out some not-so-useful information about the object's internal identifier. If we override this method, however, we can make it display some more useful information. Let's do so in our `Vehicle` and `Car` class as an example:
|
||||
```java
|
||||
// Vehicle.java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
|
||||
public Vehicle(int amountOfWheels) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Vehicle with " + this.amountOfWheels + " wheels";
|
||||
}
|
||||
}
|
||||
|
||||
// Truck.java
|
||||
public class Truck extends Vehicle {
|
||||
public int storageArea;
|
||||
|
||||
public Truck(int storageArea) {
|
||||
super(4);
|
||||
this.storageArea = storageArea;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String vehicleInfo = super.toString();
|
||||
return vehicleInfo + " and " + this.storageArea + " storage area";
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, `Truck` additionally calls the `toString()` super method and then appends some more information to the string created in `Vehicle`. Pretty nice.
|
||||
|
||||
## `equals()`
|
||||
Remember how I told you that you should always use `equals()` to compare two strings instead of the double equals sign `==`?
|
||||
|
||||
Well, here's why: Java's `String` class overrides the `equals()` method from `Object` and changes its behavior so that two strings are considered equal if their contents are identical.
|
||||
|
||||
As an example, let's first override the `equals()` method in our `Vehicle` class with the default behavior that it would have if you didn't override it at all:
|
||||
```java
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return this == other;
|
||||
}
|
||||
```
|
||||
As you can see, the default behavior is simply the double equals sign `==`, which compares if two variable pointers point to the exact same object, as previously explained. That's not what we might want in our example, though.
|
||||
|
||||
Let's expand our `Vehicle` class to also have a unique identifier: The license plate's text. Let's say that we want to identify each vehicle by its plate, and so we make it the key factor in determining whether two vehicles are the same or not:
|
||||
```java
|
||||
public class Vehicle {
|
||||
public int amountOfWheels;
|
||||
public String licensePlate;
|
||||
|
||||
public Vehicle(int amountOfWheels, String licensePlate) {
|
||||
this.amountOfWheels = amountOfWheels;
|
||||
this.licensePlate = licensePlate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof Vehicle) {
|
||||
Vehicle v = (Vehicle) other;
|
||||
return v.licensePlate.equals(this.licensePlate);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
As you can see, each `Vehicle` now accepts a license plate in the constructor, and the `equals()` method is overridden in a way that makes two vehicles be considered equal if their license plates match exactly.
|
||||
|
||||
Now, a great example of how this could be useful is with lists. The `ArrayList` class contains the `contains()` method, which determines if a certain element is already present in the list. Now, the cool thing is that this method uses the `equals()` method on each element to determine whether or not an element is present. We can use this behavior to check if a vehicle with a certain license plate is already in our stock pretty easily:
|
||||
```java
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
private static ArrayList<Vehicle> stock = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
stock.add(new Car(4, "AC JS 1999"));
|
||||
stock.add(new Truck(10, "AC NS 1998"));
|
||||
|
||||
Car carToCheck = new Car(4, "AC HI 1234");
|
||||
if (stock.contains(carToCheck)) {
|
||||
System.out.println("The queried car is already in our stock :)");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Obviously, in this specific example, the text won't be printed because there isn't a car with that license plate in the `stock` list.
|
||||
|
||||
# Conclusion
|
||||
So yea, today you learned about the second key concept of object orientation in Java. To put this knowledge to the test, I'm going to give you an exercise all about extending classes and overriding methods that you can try to solve if you want.
|
||||
|
||||
> Let's imagine you're trying to create a program that allows you to draw manage different shapes, namely rectangles, right angle triangles and circles. Obviously, these shapes all have different properties, like the rectangle's and triangle's side lengths and the circle's radius. All of the shapes you currently have are stored in a list. For each of the shapes, you want to be able to calculate its circumference as well as its area. To test this program, you add a couple of shapes to your list and calculate the average of all of their areas and circumferences.
|
||||
|
||||
Note that you can find some methods and constants you might need in Java's default `Math` class, namely `Math.PI` and `Math.sqrt()`, the latter of which is used to calculate a square root. If you're stuck, you can [check my solution](https://gist.github.com/Ellpeck/8cf63c747313e070b7475d99e2bed5a1).
|
||||
|
||||
As always, happy coding!
|
||||
|
||||
***
|
||||
|
||||
[^1]: Annotations are another rather advanced topic that almost never comes up when using Java. They can be useful sometimes, but you'll hardly ever have a use for them.
|
||||
|
||||
[^2]: Which, in this case, would obviously be a bit of a nonsensical order to display this information in. But you get the idea.
|
|
@ -1,56 +1,56 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 🔮 The Future of Actually Additions
|
||||
summary: Not wanting to accept the fate of Actually Additions, someone has come to its rescue. 1.16, here we come?
|
||||
tags: [Minecraft]
|
||||
discuss: https://twitter.com/Ellpeck/status/1330938597785169925
|
||||
---
|
||||
|
||||
*TLDR: Actually Additions for 1.16.4 in the future. No ETA. No Fabric port. No 1.13, 1.14 or 1.15. Beautiful art overhaul. Don't ask Ellpeck anything ever. Stay awesome.*
|
||||
|
||||
**November 2021 update: The port is still being actively worked on. You can stay up to date with the progress through [the `1.16` branch](https://github.com/Ellpeck/ActuallyAdditions/tree/1.16) on the GitHub repository.**
|
||||
|
||||
Before I start this post, I want to re-iterate that I haven't had a direct programming-related connection to Actually Additions in [over three years](https://github.com/Ellpeck/ActuallyAdditions/commits/main?after=896a082d747a3e19755ded1973544d59fa992787+244). I don't plan on changing this. This means that, if you have *anything* to say about the mod, be it issue reports or feature requests, **do not talk to me about that**. Go to [the issue tracker](https://github.com/Ellpeck/ActuallyAdditions/issues) or [my Discord](https://ellpeck.de/discord)'s `#minecraft` channel.
|
||||
|
||||
Okay, now that that's out of the way... let's talk about the future of Actually Additions. In [my last post](https://ellpeck.de/blog-actually_additions), I talked about the things I disliked about the mod and, in that same vein, the reasons that I don't want it to be updated beyond Minecraft 1.12. What I didn't necessarily make clear in that post is that this isn't really my decision, because I haven't touched Actually Additions in *a long time*. For the last few years, **Shadows-of-Fire** has been maintaining the mod (that is, fixing issues and publishing updates), which is also the reason that there haven't been any new features during that time. So what about now?
|
||||
|
||||
# Who?
|
||||
A few months ago, Direwolf sent me a message on Discord along the lines of
|
||||
|
||||
> Hey, do you want someone to port Actually Additions? Because I know this really great guy called [MiKeY](https://github.com/MichaelHillcox) who really loves porting mods for some reason.
|
||||
|
||||
So, as a result of that, **MiKeY** is basically the new, official maintainer of Actually Additions.
|
||||
|
||||
A little while later, another person approached me: [Ridanisaurus](https://github.com/Ridanisaurus), who apparently really likes making beautiful art for mods. He asked me if I want new art for Actually Additions, and since I have some *opinions* about the current state of Actually Additions' graphics and visual consistency, I naturally said yes immediately. So yea, **Ridanisaurus** is basically the new, official artist of Actually Additions.
|
||||
|
||||
# What?
|
||||
MiKeY and Rid are going to port Actually Additions to **Forge** for **Minecraft 1.16.4**. They are re-doing all of the art for the mod and they will also modify some of the features that I dislike, based on my personal feedback and the information outlined in [my diss track](https://ellpeck.de/blog-actually_additions).
|
||||
|
||||
The art overhaul has already started (and even been finished, I believe), and because it is *gorgeous*, I'm going to show you some of the preview pictures that Rid has sent me right now. Enjoy.
|
||||
|
||||
<img src="/blog/res/future_actually_additions/1.png" width="100%">
|
||||
|
||||
<img src="/blog/res/future_actually_additions/2.png" width="100%">
|
||||
|
||||
<img src="/blog/res/future_actually_additions/3.png" width="100%">
|
||||
|
||||
Don't they look *so good*?
|
||||
|
||||
# What Not?
|
||||
Since I know a lot of people will ask questions about this, here is a list of some of the things that you will **not** be getting, no matter how frequently you ask.
|
||||
- We will *not* be releasing a Fabric version of the mod.
|
||||
- We will *not* be releasing 1.13, 1.14 or 1.15 versions of the mod.
|
||||
- We will *not* be keeping all of the features in the mod the same, especially not the Storage Crate, which will be getting a major overhaul.
|
||||
- There will be *no* entirely new features, only changes to existing ones. Since this has been the case for the last few years as well, I don't think it's very surprising.
|
||||
|
||||
MiKeY has expressed great interest in helping me overhaul the features that I dislike and, as a result, making Actually Additions a better and more refined mod than it used to be.
|
||||
|
||||
# When?
|
||||
We don't know yet. *Please* don't ask.
|
||||
|
||||
**November 2021 update: We still don't know. It's a process.**
|
||||
|
||||
# Thank You
|
||||
So yea, that's about it for the news. I hope all of you are as excited about the port and the upcoming changes as I am. If you want to be kept up to date with the changes, you can check the [GitHub repository](https://github.com/Ellpeck/ActuallyAdditions) every once in a while (specifically [its `1.16` branch](https://github.com/Ellpeck/ActuallyAdditions/tree/1.16)) and join [my Discord server](https://ellpeck.de/discord), where we might post some updates from time to time.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 🔮 The Future of Actually Additions
|
||||
description: Not wanting to accept the fate of Actually Additions, someone has come to its rescue. 1.16, here we come?
|
||||
tags: [Minecraft]
|
||||
discuss: https://twitter.com/Ellpeck/status/1330938597785169925
|
||||
---
|
||||
|
||||
*TLDR: Actually Additions for 1.16.4 in the future. No ETA. No Fabric port. No 1.13, 1.14 or 1.15. Beautiful art overhaul. Don't ask Ellpeck anything ever. Stay awesome.*
|
||||
|
||||
**November 2021 update: The port is still being actively worked on. You can stay up to date with the progress through [the `1.16` branch](https://github.com/Ellpeck/ActuallyAdditions/tree/1.16) on the GitHub repository.**
|
||||
|
||||
Before I start this post, I want to re-iterate that I haven't had a direct programming-related connection to Actually Additions in [over three years](https://github.com/Ellpeck/ActuallyAdditions/commits/main?after=896a082d747a3e19755ded1973544d59fa992787+244). I don't plan on changing this. This means that, if you have *anything* to say about the mod, be it issue reports or feature requests, **do not talk to me about that**. Go to [the issue tracker](https://github.com/Ellpeck/ActuallyAdditions/issues) or [my Discord](https://ellpeck.de/discord)'s `#minecraft` channel.
|
||||
|
||||
Okay, now that that's out of the way... let's talk about the future of Actually Additions. In [my last post](https://ellpeck.de/blog-actually_additions), I talked about the things I disliked about the mod and, in that same vein, the reasons that I don't want it to be updated beyond Minecraft 1.12. What I didn't necessarily make clear in that post is that this isn't really my decision, because I haven't touched Actually Additions in *a long time*. For the last few years, **Shadows-of-Fire** has been maintaining the mod (that is, fixing issues and publishing updates), which is also the reason that there haven't been any new features during that time. So what about now?
|
||||
|
||||
# Who?
|
||||
A few months ago, Direwolf sent me a message on Discord along the lines of
|
||||
|
||||
> Hey, do you want someone to port Actually Additions? Because I know this really great guy called [MiKeY](https://github.com/MichaelHillcox) who really loves porting mods for some reason.
|
||||
|
||||
So, as a result of that, **MiKeY** is basically the new, official maintainer of Actually Additions.
|
||||
|
||||
A little while later, another person approached me: [Ridanisaurus](https://github.com/Ridanisaurus), who apparently really likes making beautiful art for mods. He asked me if I want new art for Actually Additions, and since I have some *opinions* about the current state of Actually Additions' graphics and visual consistency, I naturally said yes immediately. So yea, **Ridanisaurus** is basically the new, official artist of Actually Additions.
|
||||
|
||||
# What?
|
||||
MiKeY and Rid are going to port Actually Additions to **Forge** for **Minecraft 1.16.4**. They are re-doing all of the art for the mod and they will also modify some of the features that I dislike, based on my personal feedback and the information outlined in [my diss track](https://ellpeck.de/blog-actually_additions).
|
||||
|
||||
The art overhaul has already started (and even been finished, I believe), and because it is *gorgeous*, I'm going to show you some of the preview pictures that Rid has sent me right now. Enjoy.
|
||||
|
||||
<img src="/blog/res/future_actually_additions/1.png" width="100%">
|
||||
|
||||
<img src="/blog/res/future_actually_additions/2.png" width="100%">
|
||||
|
||||
<img src="/blog/res/future_actually_additions/3.png" width="100%">
|
||||
|
||||
Don't they look *so good*?
|
||||
|
||||
# What Not?
|
||||
Since I know a lot of people will ask questions about this, here is a list of some of the things that you will **not** be getting, no matter how frequently you ask.
|
||||
- We will *not* be releasing a Fabric version of the mod.
|
||||
- We will *not* be releasing 1.13, 1.14 or 1.15 versions of the mod.
|
||||
- We will *not* be keeping all of the features in the mod the same, especially not the Storage Crate, which will be getting a major overhaul.
|
||||
- There will be *no* entirely new features, only changes to existing ones. Since this has been the case for the last few years as well, I don't think it's very surprising.
|
||||
|
||||
MiKeY has expressed great interest in helping me overhaul the features that I dislike and, as a result, making Actually Additions a better and more refined mod than it used to be.
|
||||
|
||||
# When?
|
||||
We don't know yet. *Please* don't ask.
|
||||
|
||||
**November 2021 update: We still don't know. It's a process.**
|
||||
|
||||
# Thank You
|
||||
So yea, that's about it for the news. I hope all of you are as excited about the port and the upcoming changes as I am. If you want to be kept up to date with the changes, you can check the [GitHub repository](https://github.com/Ellpeck/ActuallyAdditions) every once in a while (specifically [its `1.16` branch](https://github.com/Ellpeck/ActuallyAdditions/tree/1.16)) and join [my Discord server](https://ellpeck.de/discord), where we might post some updates from time to time.
|
||||
|
||||
As an additional note, I would like to thank all of you for the continued support of not only Actually Additions, but all of my mods and even my non-Minecraft-related projects. Of course, there have also been some rude people, but all in all, yall have been an amazing community and I am so grateful that you enjoy the things I create. I love yall. ❤️
|
|
@ -1,100 +1,100 @@
|
|||
---
|
||||
layout: blog
|
||||
title: ⛔ Oh God, Please Don't Port Actually Additions
|
||||
summary: As Actually Additions celebrates its fifth birthday, I break down what I like and dislike about it.
|
||||
tags: [Minecraft]
|
||||
discuss: https://twitter.com/Ellpeck/status/1259600490377216002
|
||||
---
|
||||
|
||||
On March 7 of this year, my overwhelmingly popular Minecraft mod Actually Additions [celebrated its fifth birthday](https://www.curseforge.com/minecraft/mc-mods/actually-additions/files/2229705). I personally made my last real contribution to the project [around mid-June 2017](https://github.com/Ellpeck/ActuallyAdditions/commits/main?after=896a082d747a3e19755ded1973544d59fa992787+244), so basically three years ago. Every now and again, though (and by that, I mean almost constantly), I still get asked about the project. The main question I get is: "Will you port Actually Additions to Minecraft 1.15?"
|
||||
|
||||
Here's the short answer: No, I won't. I haven't worked on the project in *three years*. But this post isn't about that. It's about why *you* probably shouldn't port it either.
|
||||
|
||||
I've grown a lot in the last five years. Yes, I've literally grown in the last five years - I'm 20 years old now. But I've also grown as a programmer, and more importantly, as a game designer. In this post, I'm going to reminisce about some features of Actually Additions, tell you why I added them, how I added them and what I'd do differently if I made the mod today. Since I can't be bothered opening a modpack instance, I'm just going to go off of the information from the [online manual](https://ellpeck.de/actaddmanual/) for this list.
|
||||
|
||||
# "Actually Additions"
|
||||
When first starting out with the mod, it was called something like "Some Pretty Techy Stuff". I realized that was a *terrible* name choice though, so I changed it to "Some Pretty *Random* Stuff" pretty quickly. That wasn't much better, so after some (evidently not very much) consideration, I apparently settled on *the worst possible mod name*, "Actually Additions". It makes no grammatical sense unless you add a comma, and it's annoying to say for me because, as any non-native English speaker knows, saying "Actually" is very hard.
|
||||
|
||||
# Overpowered Items
|
||||
A lot of items in Actually Additions suffer the exact same problem: They're *balanced because they take effort*. What that means is that they're overpowered beyond belief, because they usually take a somewhat large amount of resources to create (though that isn't even true for some of them) and then do something crazy at (basically) no cost. All of these items are ones I'd either implement completely differently today, or scrap entirely:
|
||||
- The Fishing Net
|
||||
- Greenhouse Glass
|
||||
- The Item Repairer
|
||||
- The Ring of Growth
|
||||
|
||||
## Oh God, Storage Crates
|
||||
Why do people love them so much? They make every other mod's storage options *completely worthless*. Why they're not disabled in more modpacks is a complete mystery to me.
|
||||
|
||||
I don't think there's any code I've written in my life that I regret as much as Storage Crates. God, they're awful.
|
||||
|
||||
## Solar Panels
|
||||
When I first implemented them, I thought passive power generation was perfectly fine. That opinion changed pretty quickly the more I got used to working with RF-based mods and the struggle of trying to balance them against each other. So... I changed solar panels to be ridiculously expensive and only generate 8 RF per tick, which is a rather small amount.
|
||||
|
||||
Still, a lot of people kept on using them. *Creative*.
|
||||
|
||||
If you really, *really* want to port Actually Additions to 1.15, at least remove all of these unbalanced features first. Or at least try to make them less horrible somehow.
|
||||
|
||||
# Phantomfaces
|
||||
I still, to this day, *adore* the way I implemented Phantomfaces. They look good, they work well, they have unique functionality, but... **everyone uses them wrong**. They're not supposed to be a means of item transportation. How could I make them be more restricted to their intended use case? I don't really know, honestly.
|
||||
|
||||
# The Coffee Maker
|
||||
Etho is my favorite YouTuber of all time, and always has been. When he first used the Coffee Maker in his HermitCraft modded series, I legitimately cried of happiness. Following that point, he made and used it in every modded series that it was available in.
|
||||
|
||||
I still think it's a great block with awesomely unique functionality, and I have been considering implementing something similar in functionality into my newer mod Nature's Aura.
|
||||
|
||||
# Canola and Oil
|
||||
There's not much to say about the entire canola power generation system other than... I love it. I think it's a great way to generate power in almost every modpack. It's easy to set up, it scales well to higher tiers of power generation and it's a fun thing to automate. It makes me happy to see that a lot of people seem to still agree nowadays.
|
||||
|
||||
# Wings of the Bats
|
||||
I'm not the *biggest* fan of creative flight in survival mode anymore in general, but I do like how I implemented the Wings of the Bats. For those of you who don't know: They have a charge that runs out when you fly with them. If you land on the ground, the charge slowly fills back up again. *But* if you fly up to the ceiling and hover there for a while, the charge fills up a lot faster than if you were to stand on the ground. Because you're a bat.
|
||||
|
||||
# AIOTS
|
||||
...were a huge mistake. "All-In-One-Tools", originally called something ridiculous like "Paxelordoe" (Pickaxe, Shovel, Sword and Hoe), were pretty much intended to be a better version of Mekanism's paxels. I like the idea of all-in-one tools in general, but I think they should be later game. I also think they should *not* have **eight times** the durability of the tools they were made from.
|
||||
|
||||
# Laser Relays
|
||||
Laser Relays were my sorry attempt at copying Immersive Engineering's awesome wires. Did I succeed in that? No. But did I still make something hella awesome? Yes. As with all of the other things on this list that I actually do like, they scale well and they look good.
|
||||
|
||||
I personally especially love the item laser relays, because they can do almost as much as logistics pipes can, minus the request terminal. Do people that use them realize that? Most of the time, no. Is there a way to fix that? Probably, but I don't know what it is.
|
||||
|
||||
# The Atomic Reconstructor
|
||||
...is awesome, plain and simple. This is one of the features I added surprisingly late in development, probably a year or so after the mod originally came out, if I had to guess. The reason I like it so much is that I'm a huge fan of in-world crafting. It's less boring than sitting in front of some UI-heavy machine, and it's more fun to automate too. If I made Actually Additions again today, the Atomic Reconstructor would still be the mod's centerpiece. Also, the lenses are cool.
|
||||
|
||||
The crystals, though... I don't think I'd want them to work the same nowadays. The names were ridiculous, the textures were weird and the materials used to make them were generic and boring. Actually, I originally picked the ridiculous anagram-ish names specifically because I *knew* YouTubers would have trouble saying them, and the thought of that was hilarious to me.
|
||||
|
||||
# Lush Caves
|
||||
They don't fit the mod (because it's not a biome/world gen mod), so most modpacks disable them. I don't really understand why, though, because they add so much to the world!
|
||||
|
||||
This game desperately needs a cave update.
|
||||
|
||||
# The Textures
|
||||
The textures for Actually Additions were created by three separate artists, as well as *me*, the latter of which is very far from an artist.
|
||||
|
||||
That's why the visual style of the mod is inconsistent and honestly pretty gross. The textures of blocks don't fit together, most of them are flat and uninspired. The mod doesn't use that many nice particles and other visual effects to enhance the look and feel of mechanics.
|
||||
|
||||
Altogether, when playing the mod now, the texture and overall visual style of the mod make me feel like I'm playing some bizarre combination of old ruins, a tech mod and a confused magic mod.
|
||||
|
||||
# Honorable-ish Mentions
|
||||
**Black Quartz**. Why didn't I make it drop the item directly instead of the ore? I don't know. Weird choice, though.
|
||||
|
||||
**Smiley Clouds**. God, they're creepy. Yes, they were just supposed to be a clone of Botania's Tiny Potato. Were they as well designed? No. Were they as cool? No. Would I ever want them in my life ever again? Definitely not.
|
||||
|
||||
**Treasure Chests**. I like the feature, but... does anyone even know they exist?
|
||||
|
||||
**ESDs** were actually one of the first features in the mod. I still like them, though their UI is clunky and hard to understand. If I made Actually Additions today, I'd definitely include them, but with a different name and a cleaner UI.
|
||||
|
||||
**Experience Solidifiers** are great. I like the solidified experience too, though I know that a lot of modpack makers seem to disagree, as it's disabled in almost every pack. I'd still want them today, though.
|
||||
|
||||
**The Feeder** is an almost exact copy of the Railcraft Feeding Station thing, because back in the day, I was so unoriginal that I just stole other people's content. Yea.
|
||||
|
||||
**Drills**. Love 'em. The upgrade system is neat and scales well, they use a good amount of power and they just look *so cool*.
|
||||
|
||||
**Balls of Fur** are actually called "hairy balls." I don't know if the fact that I *didn't* realize that that wasn't the best name when implementing them makes this whole situation less embarrassing or more embarrassing.
|
||||
|
||||
**The Empowerer** is still pretty cool in my opinion. I'd probably use it as a crafting mechanic again.
|
||||
|
||||
# What Do We Learn From This?
|
||||
Well, I don't know if you learn anything from this, but there's one thing I learned for sure: I'm a lot better of a programmer and a lot better of a game designer now.
|
||||
|
||||
Sure, I'd still consider Actually Additions to be a pretty good mod, and it's definitely a nice project to be known for. But I don't think I'd do almost anything in the mod the same way nowadays.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: ⛔ Oh God, Please Don't Port Actually Additions
|
||||
description: As Actually Additions celebrates its fifth birthday, I break down what I like and dislike about it.
|
||||
tags: [Minecraft]
|
||||
discuss: https://twitter.com/Ellpeck/status/1259600490377216002
|
||||
---
|
||||
|
||||
On March 7 of this year, my overwhelmingly popular Minecraft mod Actually Additions [celebrated its fifth birthday](https://www.curseforge.com/minecraft/mc-mods/actually-additions/files/2229705). I personally made my last real contribution to the project [around mid-June 2017](https://github.com/Ellpeck/ActuallyAdditions/commits/main?after=896a082d747a3e19755ded1973544d59fa992787+244), so basically three years ago. Every now and again, though (and by that, I mean almost constantly), I still get asked about the project. The main question I get is: "Will you port Actually Additions to Minecraft 1.15?"
|
||||
|
||||
Here's the short answer: No, I won't. I haven't worked on the project in *three years*. But this post isn't about that. It's about why *you* probably shouldn't port it either.
|
||||
|
||||
I've grown a lot in the last five years. Yes, I've literally grown in the last five years - I'm 20 years old now. But I've also grown as a programmer, and more importantly, as a game designer. In this post, I'm going to reminisce about some features of Actually Additions, tell you why I added them, how I added them and what I'd do differently if I made the mod today. Since I can't be bothered opening a modpack instance, I'm just going to go off of the information from the [online manual](https://ellpeck.de/actaddmanual/) for this list.
|
||||
|
||||
# "Actually Additions"
|
||||
When first starting out with the mod, it was called something like "Some Pretty Techy Stuff". I realized that was a *terrible* name choice though, so I changed it to "Some Pretty *Random* Stuff" pretty quickly. That wasn't much better, so after some (evidently not very much) consideration, I apparently settled on *the worst possible mod name*, "Actually Additions". It makes no grammatical sense unless you add a comma, and it's annoying to say for me because, as any non-native English speaker knows, saying "Actually" is very hard.
|
||||
|
||||
# Overpowered Items
|
||||
A lot of items in Actually Additions suffer the exact same problem: They're *balanced because they take effort*. What that means is that they're overpowered beyond belief, because they usually take a somewhat large amount of resources to create (though that isn't even true for some of them) and then do something crazy at (basically) no cost. All of these items are ones I'd either implement completely differently today, or scrap entirely:
|
||||
- The Fishing Net
|
||||
- Greenhouse Glass
|
||||
- The Item Repairer
|
||||
- The Ring of Growth
|
||||
|
||||
## Oh God, Storage Crates
|
||||
Why do people love them so much? They make every other mod's storage options *completely worthless*. Why they're not disabled in more modpacks is a complete mystery to me.
|
||||
|
||||
I don't think there's any code I've written in my life that I regret as much as Storage Crates. God, they're awful.
|
||||
|
||||
## Solar Panels
|
||||
When I first implemented them, I thought passive power generation was perfectly fine. That opinion changed pretty quickly the more I got used to working with RF-based mods and the struggle of trying to balance them against each other. So... I changed solar panels to be ridiculously expensive and only generate 8 RF per tick, which is a rather small amount.
|
||||
|
||||
Still, a lot of people kept on using them. *Creative*.
|
||||
|
||||
If you really, *really* want to port Actually Additions to 1.15, at least remove all of these unbalanced features first. Or at least try to make them less horrible somehow.
|
||||
|
||||
# Phantomfaces
|
||||
I still, to this day, *adore* the way I implemented Phantomfaces. They look good, they work well, they have unique functionality, but... **everyone uses them wrong**. They're not supposed to be a means of item transportation. How could I make them be more restricted to their intended use case? I don't really know, honestly.
|
||||
|
||||
# The Coffee Maker
|
||||
Etho is my favorite YouTuber of all time, and always has been. When he first used the Coffee Maker in his HermitCraft modded series, I legitimately cried of happiness. Following that point, he made and used it in every modded series that it was available in.
|
||||
|
||||
I still think it's a great block with awesomely unique functionality, and I have been considering implementing something similar in functionality into my newer mod Nature's Aura.
|
||||
|
||||
# Canola and Oil
|
||||
There's not much to say about the entire canola power generation system other than... I love it. I think it's a great way to generate power in almost every modpack. It's easy to set up, it scales well to higher tiers of power generation and it's a fun thing to automate. It makes me happy to see that a lot of people seem to still agree nowadays.
|
||||
|
||||
# Wings of the Bats
|
||||
I'm not the *biggest* fan of creative flight in survival mode anymore in general, but I do like how I implemented the Wings of the Bats. For those of you who don't know: They have a charge that runs out when you fly with them. If you land on the ground, the charge slowly fills back up again. *But* if you fly up to the ceiling and hover there for a while, the charge fills up a lot faster than if you were to stand on the ground. Because you're a bat.
|
||||
|
||||
# AIOTS
|
||||
...were a huge mistake. "All-In-One-Tools", originally called something ridiculous like "Paxelordoe" (Pickaxe, Shovel, Sword and Hoe), were pretty much intended to be a better version of Mekanism's paxels. I like the idea of all-in-one tools in general, but I think they should be later game. I also think they should *not* have **eight times** the durability of the tools they were made from.
|
||||
|
||||
# Laser Relays
|
||||
Laser Relays were my sorry attempt at copying Immersive Engineering's awesome wires. Did I succeed in that? No. But did I still make something hella awesome? Yes. As with all of the other things on this list that I actually do like, they scale well and they look good.
|
||||
|
||||
I personally especially love the item laser relays, because they can do almost as much as logistics pipes can, minus the request terminal. Do people that use them realize that? Most of the time, no. Is there a way to fix that? Probably, but I don't know what it is.
|
||||
|
||||
# The Atomic Reconstructor
|
||||
...is awesome, plain and simple. This is one of the features I added surprisingly late in development, probably a year or so after the mod originally came out, if I had to guess. The reason I like it so much is that I'm a huge fan of in-world crafting. It's less boring than sitting in front of some UI-heavy machine, and it's more fun to automate too. If I made Actually Additions again today, the Atomic Reconstructor would still be the mod's centerpiece. Also, the lenses are cool.
|
||||
|
||||
The crystals, though... I don't think I'd want them to work the same nowadays. The names were ridiculous, the textures were weird and the materials used to make them were generic and boring. Actually, I originally picked the ridiculous anagram-ish names specifically because I *knew* YouTubers would have trouble saying them, and the thought of that was hilarious to me.
|
||||
|
||||
# Lush Caves
|
||||
They don't fit the mod (because it's not a biome/world gen mod), so most modpacks disable them. I don't really understand why, though, because they add so much to the world!
|
||||
|
||||
This game desperately needs a cave update.
|
||||
|
||||
# The Textures
|
||||
The textures for Actually Additions were created by three separate artists, as well as *me*, the latter of which is very far from an artist.
|
||||
|
||||
That's why the visual style of the mod is inconsistent and honestly pretty gross. The textures of blocks don't fit together, most of them are flat and uninspired. The mod doesn't use that many nice particles and other visual effects to enhance the look and feel of mechanics.
|
||||
|
||||
Altogether, when playing the mod now, the texture and overall visual style of the mod make me feel like I'm playing some bizarre combination of old ruins, a tech mod and a confused magic mod.
|
||||
|
||||
# Honorable-ish Mentions
|
||||
**Black Quartz**. Why didn't I make it drop the item directly instead of the ore? I don't know. Weird choice, though.
|
||||
|
||||
**Smiley Clouds**. God, they're creepy. Yes, they were just supposed to be a clone of Botania's Tiny Potato. Were they as well designed? No. Were they as cool? No. Would I ever want them in my life ever again? Definitely not.
|
||||
|
||||
**Treasure Chests**. I like the feature, but... does anyone even know they exist?
|
||||
|
||||
**ESDs** were actually one of the first features in the mod. I still like them, though their UI is clunky and hard to understand. If I made Actually Additions today, I'd definitely include them, but with a different name and a cleaner UI.
|
||||
|
||||
**Experience Solidifiers** are great. I like the solidified experience too, though I know that a lot of modpack makers seem to disagree, as it's disabled in almost every pack. I'd still want them today, though.
|
||||
|
||||
**The Feeder** is an almost exact copy of the Railcraft Feeding Station thing, because back in the day, I was so unoriginal that I just stole other people's content. Yea.
|
||||
|
||||
**Drills**. Love 'em. The upgrade system is neat and scales well, they use a good amount of power and they just look *so cool*.
|
||||
|
||||
**Balls of Fur** are actually called "hairy balls." I don't know if the fact that I *didn't* realize that that wasn't the best name when implementing them makes this whole situation less embarrassing or more embarrassing.
|
||||
|
||||
**The Empowerer** is still pretty cool in my opinion. I'd probably use it as a crafting mechanic again.
|
||||
|
||||
# What Do We Learn From This?
|
||||
Well, I don't know if you learn anything from this, but there's one thing I learned for sure: I'm a lot better of a programmer and a lot better of a game designer now.
|
||||
|
||||
Sure, I'd still consider Actually Additions to be a pretty good mod, and it's definitely a nice project to be known for. But I don't think I'd do almost anything in the mod the same way nowadays.
|
||||
|
||||
Also, I kind of think that Actually Additions has run its course in some way; it's lived its life. It's important to remember that there is a huge amount of new, unexplored mod ideas still out there, and that there are already some great mods that implement unique, new ideas. Shouldn't we let those mods step into the spotlight now?
|
|
@ -1,22 +1,22 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 🤷 But Do You Really Care?
|
||||
summary: On taking a break from social media
|
||||
tags: [Miscellaneous]
|
||||
---
|
||||
|
||||
Over the years, my views on social media and its purpose have changed many times. When I first started out using the internet, playing Minecraft and watching YouTube videos about it, I didn't really care about social media in general. Eventually, I created a Twitter account, just to be able to follow people and see their tweets, to see what the people I cared about were... caring about. Eventually, as Discord rolled around, I first just used it to talk to my friends, but I eventually decided that a server would probably be a good idea. So I created the "Ellpeck and Friends" server, which eventually evolved into the server [that it is today](https://ellpeck.de/discord).
|
||||
|
||||
So, the more I used Discord and Twitter, the more... *obsessive* I became about them. Every time I'd write a tweet, I'd sit there, staring at my screen for the better part of half an hour, seeing if anyone would reply, if anyone would like the tweet, if anyone would retweet, if anyone had an opinion on what I was saying. *If anyone approved*. Every time I'd say something in my Discord server, I'd actively wait for people to respond. To answer my question, to react to my joke. I wanted to know *if anyone approved*. Every time I saw that little red dot appear next to the Discord icon in the taskbar, I'd instantly stop whatever I was doing and figuratively *run* into my server to see what was going on. Did someone need my help? Did someone *finally* reply to that one message I posted two hours ago? No, it was just a new server member who joined, triggering one of those weird "a new user joined" messages.
|
||||
|
||||
But... why? Why would I care so much about who liked my tweet, or who replied to it? Even if my close friends liked it, I would go "AHA, someone approves!", despite the fact that I *know* that my friends approve of most of the things I do - that's kind of what friends just do. Why did I care so much about a stupid message in my stupid Discord server? Why did I *desperately* want the person that just posted "when will you update Actually Additions to 1.15?" to reply to what I answered? They were just a stranger. It's not like their opinion actually matters when it comes to me and my life. But somehow, it still mattered *to me*.
|
||||
|
||||
So the other day, I just decided... no. This wasn't what I was going to do anymore. I wasn't going to let some dumb, scream-into-the-void social media platforms control my life anymore. So, before bed that night, I quickly deleted Discord and Twitter off of my computer, and off of my phone. Ever since, my phone's homescreen has had two blatantly visible empty spaces.
|
||||
|
||||
It's been about two weeks since I did that, and... I've honestly been feeling really good about it. I started occasionally checking Twitter again, but never just to see notifications or to see if someone replied to any of my tweets. I only ever look at it if I want to tweet, or if I'm curious about what someone else has been tweeting about recently. Last night, I opened Discord from the browser to check if any of my friends have been messaging me there. There were a couple of notifications, which I replied to. I also checked my server, and *oh my God*, did I feel good about taking a break from that. There were a bunch of messages from people asking about my mods, and how to do certain things. There weren't any important messages, anything that, if I missed it, would change my life in some way. I didn't *need* to be there.
|
||||
|
||||
I realized that I shouldn't care that much what other people think about me; neither on social media, nor in real life. It's an unnecessary hassle to make sure that everyone loves you, that you don't make any mistakes, that you only have opinions that other people approve of. The important part is that you approve of *yourself*, and that the people you care about also care about you.
|
||||
|
||||
So... if you're feeling like there's a lot of pressure on you whenever you tweet, or send a message in a Discord server, or write a Facebook post, then maybe you should try just not doing that for a little while. It might make you feel a bit better.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 🤷 But Do You Really Care?
|
||||
description: On taking a break from social media
|
||||
tags: [Miscellaneous]
|
||||
---
|
||||
|
||||
Over the years, my views on social media and its purpose have changed many times. When I first started out using the internet, playing Minecraft and watching YouTube videos about it, I didn't really care about social media in general. Eventually, I created a Twitter account, just to be able to follow people and see their tweets, to see what the people I cared about were... caring about. Eventually, as Discord rolled around, I first just used it to talk to my friends, but I eventually decided that a server would probably be a good idea. So I created the "Ellpeck and Friends" server, which eventually evolved into the server [that it is today](https://ellpeck.de/discord).
|
||||
|
||||
So, the more I used Discord and Twitter, the more... *obsessive* I became about them. Every time I'd write a tweet, I'd sit there, staring at my screen for the better part of half an hour, seeing if anyone would reply, if anyone would like the tweet, if anyone would retweet, if anyone had an opinion on what I was saying. *If anyone approved*. Every time I'd say something in my Discord server, I'd actively wait for people to respond. To answer my question, to react to my joke. I wanted to know *if anyone approved*. Every time I saw that little red dot appear next to the Discord icon in the taskbar, I'd instantly stop whatever I was doing and figuratively *run* into my server to see what was going on. Did someone need my help? Did someone *finally* reply to that one message I posted two hours ago? No, it was just a new server member who joined, triggering one of those weird "a new user joined" messages.
|
||||
|
||||
But... why? Why would I care so much about who liked my tweet, or who replied to it? Even if my close friends liked it, I would go "AHA, someone approves!", despite the fact that I *know* that my friends approve of most of the things I do - that's kind of what friends just do. Why did I care so much about a stupid message in my stupid Discord server? Why did I *desperately* want the person that just posted "when will you update Actually Additions to 1.15?" to reply to what I answered? They were just a stranger. It's not like their opinion actually matters when it comes to me and my life. But somehow, it still mattered *to me*.
|
||||
|
||||
So the other day, I just decided... no. This wasn't what I was going to do anymore. I wasn't going to let some dumb, scream-into-the-void social media platforms control my life anymore. So, before bed that night, I quickly deleted Discord and Twitter off of my computer, and off of my phone. Ever since, my phone's homescreen has had two blatantly visible empty spaces.
|
||||
|
||||
It's been about two weeks since I did that, and... I've honestly been feeling really good about it. I started occasionally checking Twitter again, but never just to see notifications or to see if someone replied to any of my tweets. I only ever look at it if I want to tweet, or if I'm curious about what someone else has been tweeting about recently. Last night, I opened Discord from the browser to check if any of my friends have been messaging me there. There were a couple of notifications, which I replied to. I also checked my server, and *oh my God*, did I feel good about taking a break from that. There were a bunch of messages from people asking about my mods, and how to do certain things. There weren't any important messages, anything that, if I missed it, would change my life in some way. I didn't *need* to be there.
|
||||
|
||||
I realized that I shouldn't care that much what other people think about me; neither on social media, nor in real life. It's an unnecessary hassle to make sure that everyone loves you, that you don't make any mistakes, that you only have opinions that other people approve of. The important part is that you approve of *yourself*, and that the people you care about also care about you.
|
||||
|
||||
So... if you're feeling like there's a lot of pressure on you whenever you tweet, or send a message in a Discord server, or write a Facebook post, then maybe you should try just not doing that for a little while. It might make you feel a bit better.
|
||||
|
||||
*This post won't have a discussion link, for obvious reasons.*
|
|
@ -1,146 +1,146 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 🍝 Ketchup, Mayo and Barbecue Sauce
|
||||
summary: "Sally can't quite decide what skirt to buy. When she starts going out for lunch with David, an old crush from high school, she can't quite decide what to order. But she's sure about one thing: She likes David. A lot."
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
reedsy: https://blog.reedsy.com/creative-writing-prompts/contests/95/submissions/69321/
|
||||
discuss: https://twitter.com/Ellpeck/status/1398049729582407686
|
||||
---
|
||||
|
||||
Sally strolled along the shopping street with her favorite, rainbow-colored bag swung over her left shoulder. Looking around the shops, she wondered if she'd gotten everything from her list. Unsure, but willing to be *absolutely certain*, she pulled her phone out of her shiny bag and opened her notes. There was one item left on it, unticked: *short skirt, blue, summer*. She held the bag open with one hand and started rummaging through it with the other. Sally had already bought a skirt, but it wasn't blue, and it wasn't fit for summer either. It was longer, and the colors made her think of the fall. Of dancing around in the rain, of jumping straight into a pile of leaves. Of *Joey*.
|
||||
|
||||
Oh, God.
|
||||
|
||||
She took the skirt out of its protective casing and checked the price tag, which was still firmly attached to the waistband. Forty-seven dollars, it said. That was a lot of money to pay for a skirt, wasn't it? She jerked around on the busy street in an instant, almost bumping into a stranger, while trying to locate the store where she'd gotten this stupid thing.
|
||||
|
||||
Ah, there it was. Without thinking much, she stuffed the skirt back into her bag and headed straight for the entrance of the small boutique.
|
||||
|
||||
As she started scanning the other skirts on the racks close to the entrance, she concluded that this store was clearly ill-fitting for her goal of completing the last item on her to-do list. There were no skirts in fun, summery colors. Slightly outraged, and about ready to head to the counter to return the expensive fall skirt, she noticed a familiar face in line for the register.
|
||||
|
||||
Was it really--? No, it couldn't have been. As the long-haired guy turned around, she quickly ducked behind one of the racks as to not make it seem like she'd just been staring at him. Naturally. What could be a better way to make it seem like you're *totally* minding your own business than hiding under some random clothes rack like a nine-year-old?
|
||||
|
||||
Oh, well. It was too late now to seem normal.
|
||||
|
||||
As she raised her head carefully above the rack, just enough to be able to spy-- look at David, she realized how much he'd changed since the last time she saw him. He was wearing a flashy jacket, not the weird high school varsity kind, but a punky sort of dark, possibly faux-leather looking thing. His shoulders were--wow, his shoulders were broad, and they looked strong as hell. How much had he been lifting? Did he carry boulders for fun? For only a quick second, definitely absolutely not for longer, she imagined him scooping her up and carrying her like a princess. She imagined herself, staring up into his dark brown eyes, wondering what it would be like to look into them before she fell asleep.
|
||||
|
||||
Joey would've never done anything like that with her. It wasn't that he hadn't been strong enough to carry her or anything, it's that he just wasn't the *romantic* type. The type of person to kiss her out of nowhere, the type to turn around while walking next to her and pull her into a tight, warm embrace. But David, *oh, David*, maybe he could be that, for her.
|
||||
|
||||
After a few more minutes of dreaming, and possibly a tiny bit of *drooling*, she caught herself doing exactly the thing that she promised herself she'd never do again: *Pining* for someone, someone who probably didn't even remember she existed. Someone she hadn't even *talked to* yet. Jesus Christ.
|
||||
|
||||
She needed to get her act together, she thought to herself. And what better way to do that than to return that ugly fall skirt she'd bought and get a perfect, blue summer one just like her to-do list demanded of her. She sat up, turned away from David, who looked like he was almost finished checking out by now, and pulled the stupid skirt back out of her bag. But looking at it, she realized again how beautiful the pattern on it was. How the thin lines connected to form what looked like a network of pathways, or maybe a tree with thousands of small branches.
|
||||
|
||||
She stuffed the skirt right back into her bag and deliberated. She could always just get the blue summer skirt *on top* of the fall one, and keep both. But surely, she'd never *wear* both of them, because she already had so many other skirts, and dresses, and jeans. Why did she have *so many clothes*? She didn't even need to buy any more today. This whole thing was so unnecessary, she realized.
|
||||
|
||||
Determined to keep the skirt (because of the beautiful lines, et cetera), but not buy another skirt (because of the full closet), she headed straight for the exit with big, confident strides. So confident, in fact, that she ran right into the backside of none other than David, who had stopped in the doorway of the store, probably to check his phone or something.
|
||||
|
||||
Oh, fucking hell.
|
||||
|
||||
David leapt forward immediately and scrambled to keep his phone in his hand. He turned around and shot Sally a weird look.
|
||||
|
||||
"I'm so sorry," she mumbled, sounding overly apologetic. "I didn't look where I was going."
|
||||
|
||||
"It's no problem," he said and the corner of his mouth tilted upwards a little. "Wait, don't I know you from somewhere?"
|
||||
|
||||
Sally paused. A person who *hadn't* just stalked her old high school classmate from behind a fucking skirt rack would probably be confused for a second before, like her, immediately saying "Yea, hi, I'm Sally, back from school."
|
||||
|
||||
He arched an eyebrow. "Sally...," he began. "Sally, like, debate team Sally?"
|
||||
|
||||
"Is that what you thought of me as?", she said almost instinctively. "I didn't even do it for that long."
|
||||
|
||||
"Well," David began awkwardly and stuffed his phone into his pocket. "The other Sally made it hard to think of you as just 'Sally'", he explained.
|
||||
|
||||
Ah, that made a lot of sense, actually. Sally (the other one) was one of the popular girls, and *this* Sally was never that popular at school, or anywhere, really. She hung around the debate team for a while, but quit fairly quickly and moved on to a different club. And right now, still standing in the doorway of the store, awkwardly looking at David, she pulled a face and tried to remember what she *did* after she quit the debate team.
|
||||
|
||||
"Anyway," David said with a blank expression. "I was about to grab lunch..."
|
||||
|
||||
He paused, and Sally just kind of stared. She was still thinking about that damn club.
|
||||
|
||||
"You want to come?" David finally said.
|
||||
|
||||
"Uh, what?" Sally began awkwardly. It took a second for her brain to process what David had just said. "Oh, yea, sure, that sounds great!", and it really *did* sound great to her, too.
|
||||
|
||||
***
|
||||
|
||||
Sally couldn't quite believe it, but David had actually given her his *phone number* after their lunch date thing. They'd walked to a nearby fast food place and both ordered a burger and fries, and, while waiting for the food to arrive, they'd talked about what both of them had started doing after finishing school.
|
||||
|
||||
Sally was sitting in her bed now and looking down at her phone, the bright screen displaying David's contact information. He'd entered his first name only, along with his phone number. For a moment, Sally wondered if he might have given her some sort of fake number, but that wouldn't make much sense, because *he* was the one who'd invited her to lunch, after all.
|
||||
|
||||
She hovered over the green call button with her thumb, considering her options. Maybe she should just text him? What would she say, though? A call just seemed easier. Plus, it was cheaper, right? With her contract and all. Finally, she tapped the button with a shaky finger.
|
||||
|
||||
"Hello?" a familiar voice said on the other end of the line.
|
||||
|
||||
"Hey, it's me, Sally, from lunch," she said awkwardly. "Do you want to go out again, maybe?"
|
||||
|
||||
Wow, that was *bold* of her, wasn't it? What had gotten into her all of a sudden? She never used to be like this with Joey, or anyone else, for that matter. She shook her head and followed up with a *super* smooth "Only if you want, though. Of course." Fucking hell.
|
||||
|
||||
"I'd love to! I'm so glad you asked," he said. "I was worried you weren't going to call."
|
||||
|
||||
He was... *worried*? That was a surprise to Sally. And a nice thing to say, too, in a weird sort of way.
|
||||
|
||||
They decided to meet up for lunch again the next day, and David picked out another fast food place in town that sold Asian takeout. Sally wasn't sure if she was going to like it, but she knew she liked *David*, and that was the main thing that mattered to her.
|
||||
|
||||
Later that night, she lay awake, staring at the ceiling, thinking about David. About how nice he'd been on the phone. About lunch. *Had* he been really nice, or had she just forgotten what talking to a nice person was like? The thought was a little depressing to her, so she dismissed it as quickly as it came. No, he *had* been very nice to her, she concluded. He was a great lunch buddy.
|
||||
|
||||
***
|
||||
|
||||
David checked himself in the mirror and pulled a face. He wet his hand in the sink and tried to smooth over a rogue curl in his otherwise silky smooth, brown hair. As he let go, the stupid thing bounced back up, and he quickly admitted defeat. *Fine*, he thought to himself with a kind of confidence that he didn't normally seem to possess. *This day will go great either way.*
|
||||
|
||||
Sally had suggested a place that he'd never been to this time around, a place that--from the images online--looked to be a small restaurant with a large outdoor seating area. For a moment, he thought to himself if maybe she picked this place because it looked romantic.
|
||||
|
||||
He shrugged off the thought as a notification made his phone vibrate in his pocket. For a second, he wondered if this was Sally canceling their date-- lunch meeting-- *friendly hangout session*.
|
||||
|
||||
It was, indeed, Sally. Evidently, she hadn't messaged him to cancel, though.
|
||||
|
||||
The little banner notification at the top of his screen captured the start of her message: *been deliberating. do you mind if we go to the thai place i talked abo...* David chuckled to himself as he tapped the notification. She'd already presented him with about seventeen choices last night, asking him which one *he* would choose. What was up with that girl?
|
||||
|
||||
*Whatever you want*, he texted back. Damn it, did that sound too disinterested? *You're choosing today*, he added. He liked the idea of doing what Sally wanted. Of seeing her happy. Of *making* her happy. Why was he so into her all of a sudden?
|
||||
|
||||
*damn it*, she texted back. *reading online now that the thai place is closed, nvm*.
|
||||
|
||||
Fair enough.
|
||||
|
||||
***
|
||||
|
||||
David looked around the big seating area to spot Sally, sitting at a far table for two, awkwardly waving at him. He waved back briefly and made his way over to her. Sitting down at the table, he asked sarcastically, "Is this the place you want to eat, or should we check out some others instead?"
|
||||
|
||||
She pulled a tiny frown and rolled her eyes. "Shut up."
|
||||
|
||||
They continued bantering as they ordered food and until after their drinks arrived. This seemed to be their rapport now: Making fun of each other over drinks and varying cuisine. It was good. No, actually. It was *great*.
|
||||
|
||||
While eating his burger (and fries with mayonnaise, of course), he looked up to meet Sally's eyes for a quick moment, who smiled back before returning her focus to her own burger, also with fries and mayo. And ketchup. *And* barbecue sauce.
|
||||
Jesus Christ.
|
||||
|
||||
He continued looking at Sally for another few seconds, studying her features, taking in her eyes, which were nestled neatly between the rims of her glasses and below her long, blonde bangs. It was warm today, and Sally was wearing a flowy, bright top and a short, blue skirt that looked like she'd just bought it the same day.
|
||||
|
||||
Sally looked back up at him. "You know," she began. "I've really been enjoying our dates."
|
||||
|
||||
*Our dates*. Did she mean their lunch meetups? Or did she really mean *dates*? He gave her the benefit of the doubt, because for him, too, it was difficult to come up with names for this... arrangement.
|
||||
|
||||
"Me too," he shot back before stuffing a couple of fries into his mouth. After he swallowed, he raised an eyebrow and asked: "Dates?"
|
||||
|
||||
She looked back up at him and smiled. "I mean, if you like. We're eating, we're talking, we're... having fun." She paused. "Isn't that what a date is?"
|
||||
|
||||
David let what that sink in for a moment. He looked at her and smiled. Of course, he admitted to himself, he'd been *hoping* that these were proper dates. And sitting across from Sally, right here, right now, *knowing* that she also thought of them as *dates*... it made him feel a sort of happiness that he hadn't felt in a long time. He quietly smiled to himself and looked down at his plate again, stuffing another handful of fries into his mouth.
|
||||
|
||||
***
|
||||
|
||||
As she arrived home and unlocked the front door, Sally realized that she'd been thinking about David, and David alone, for the last few days. Whenever she watched TV and saw a cute scene, she thought of David. When chatting with her friends about their relationships, she thought of David. And, yes, she admitted to herself, she'd also thought of David while touching herself. Once or twice.
|
||||
|
||||
But that wasn't bad, she concluded. In fact, she accepted all of it as what it was: A sign that she really liked David. She smiled to herself as she went up to her room, throwing her jacket onto a chair in the corner.
|
||||
|
||||
She let herself drop backwards onto the bed like a brick and pulled out her phone, holding it over her head. She opened her message thread with David and typed the words *Today was fun.* Then, she followed up with another message: *I really like you, David.*
|
||||
|
||||
This was, for the first time since Sally could remember, something she was absolutely certain about. She didn't have to think twice before sending those messages. She didn't even *want* to think twice about them, because it was so unusually clear to her. She liked David, and there would be nothing she could tell herself, no question she could ask herself, to change that.
|
||||
|
||||
Before he even read the message, Sally moved into her contact list with a few quick swipes, scrolling down to the entries that started with the letter J. *J*, as in *Joey*, of course. She tapped his name and immediately felt a weird sense of unease, a dread that she'd always felt when she had to think about him. She scrolled down past the phone numbers and his address until, right there, in the center of her screen, was a big red button with a trash can icon and the word *Delete* next to it.
|
||||
|
||||
She thought of the lunches with David again, the way he stuffed fries into his mouth. The way he snickered when she asked the waiter for three different condiments. The way his smooth hair dissolved into more and more curls the longer he was outside in the dry summer heat. The way things seemed so *easy* with him. All of a sudden, the dread that Joey's name brought up in her vanished, just like that.
|
||||
|
||||
And then she pressed the button.
|
||||
|
||||
As she watched Joey's name slide off-screen in the contact list, all the other J names shuffling up and down neatly to fill the gap, a banner notification came down from the top of her screen. It was David.
|
||||
|
||||
*I like you too, Sally. Really like you.*
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 🍝 Ketchup, Mayo and Barbecue Sauce
|
||||
description: "Sally can't quite decide what skirt to buy. When she starts going out for lunch with David, an old crush from high school, she can't quite decide what to order. But she's sure about one thing: She likes David. A lot."
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
reedsy: https://blog.reedsy.com/creative-writing-prompts/contests/95/submissions/69321/
|
||||
discuss: https://twitter.com/Ellpeck/status/1398049729582407686
|
||||
---
|
||||
|
||||
Sally strolled along the shopping street with her favorite, rainbow-colored bag swung over her left shoulder. Looking around the shops, she wondered if she'd gotten everything from her list. Unsure, but willing to be *absolutely certain*, she pulled her phone out of her shiny bag and opened her notes. There was one item left on it, unticked: *short skirt, blue, summer*. She held the bag open with one hand and started rummaging through it with the other. Sally had already bought a skirt, but it wasn't blue, and it wasn't fit for summer either. It was longer, and the colors made her think of the fall. Of dancing around in the rain, of jumping straight into a pile of leaves. Of *Joey*.
|
||||
|
||||
Oh, God.
|
||||
|
||||
She took the skirt out of its protective casing and checked the price tag, which was still firmly attached to the waistband. Forty-seven dollars, it said. That was a lot of money to pay for a skirt, wasn't it? She jerked around on the busy street in an instant, almost bumping into a stranger, while trying to locate the store where she'd gotten this stupid thing.
|
||||
|
||||
Ah, there it was. Without thinking much, she stuffed the skirt back into her bag and headed straight for the entrance of the small boutique.
|
||||
|
||||
As she started scanning the other skirts on the racks close to the entrance, she concluded that this store was clearly ill-fitting for her goal of completing the last item on her to-do list. There were no skirts in fun, summery colors. Slightly outraged, and about ready to head to the counter to return the expensive fall skirt, she noticed a familiar face in line for the register.
|
||||
|
||||
Was it really--? No, it couldn't have been. As the long-haired guy turned around, she quickly ducked behind one of the racks as to not make it seem like she'd just been staring at him. Naturally. What could be a better way to make it seem like you're *totally* minding your own business than hiding under some random clothes rack like a nine-year-old?
|
||||
|
||||
Oh, well. It was too late now to seem normal.
|
||||
|
||||
As she raised her head carefully above the rack, just enough to be able to spy-- look at David, she realized how much he'd changed since the last time she saw him. He was wearing a flashy jacket, not the weird high school varsity kind, but a punky sort of dark, possibly faux-leather looking thing. His shoulders were--wow, his shoulders were broad, and they looked strong as hell. How much had he been lifting? Did he carry boulders for fun? For only a quick second, definitely absolutely not for longer, she imagined him scooping her up and carrying her like a princess. She imagined herself, staring up into his dark brown eyes, wondering what it would be like to look into them before she fell asleep.
|
||||
|
||||
Joey would've never done anything like that with her. It wasn't that he hadn't been strong enough to carry her or anything, it's that he just wasn't the *romantic* type. The type of person to kiss her out of nowhere, the type to turn around while walking next to her and pull her into a tight, warm embrace. But David, *oh, David*, maybe he could be that, for her.
|
||||
|
||||
After a few more minutes of dreaming, and possibly a tiny bit of *drooling*, she caught herself doing exactly the thing that she promised herself she'd never do again: *Pining* for someone, someone who probably didn't even remember she existed. Someone she hadn't even *talked to* yet. Jesus Christ.
|
||||
|
||||
She needed to get her act together, she thought to herself. And what better way to do that than to return that ugly fall skirt she'd bought and get a perfect, blue summer one just like her to-do list demanded of her. She sat up, turned away from David, who looked like he was almost finished checking out by now, and pulled the stupid skirt back out of her bag. But looking at it, she realized again how beautiful the pattern on it was. How the thin lines connected to form what looked like a network of pathways, or maybe a tree with thousands of small branches.
|
||||
|
||||
She stuffed the skirt right back into her bag and deliberated. She could always just get the blue summer skirt *on top* of the fall one, and keep both. But surely, she'd never *wear* both of them, because she already had so many other skirts, and dresses, and jeans. Why did she have *so many clothes*? She didn't even need to buy any more today. This whole thing was so unnecessary, she realized.
|
||||
|
||||
Determined to keep the skirt (because of the beautiful lines, et cetera), but not buy another skirt (because of the full closet), she headed straight for the exit with big, confident strides. So confident, in fact, that she ran right into the backside of none other than David, who had stopped in the doorway of the store, probably to check his phone or something.
|
||||
|
||||
Oh, fucking hell.
|
||||
|
||||
David leapt forward immediately and scrambled to keep his phone in his hand. He turned around and shot Sally a weird look.
|
||||
|
||||
"I'm so sorry," she mumbled, sounding overly apologetic. "I didn't look where I was going."
|
||||
|
||||
"It's no problem," he said and the corner of his mouth tilted upwards a little. "Wait, don't I know you from somewhere?"
|
||||
|
||||
Sally paused. A person who *hadn't* just stalked her old high school classmate from behind a fucking skirt rack would probably be confused for a second before, like her, immediately saying "Yea, hi, I'm Sally, back from school."
|
||||
|
||||
He arched an eyebrow. "Sally...," he began. "Sally, like, debate team Sally?"
|
||||
|
||||
"Is that what you thought of me as?", she said almost instinctively. "I didn't even do it for that long."
|
||||
|
||||
"Well," David began awkwardly and stuffed his phone into his pocket. "The other Sally made it hard to think of you as just 'Sally'", he explained.
|
||||
|
||||
Ah, that made a lot of sense, actually. Sally (the other one) was one of the popular girls, and *this* Sally was never that popular at school, or anywhere, really. She hung around the debate team for a while, but quit fairly quickly and moved on to a different club. And right now, still standing in the doorway of the store, awkwardly looking at David, she pulled a face and tried to remember what she *did* after she quit the debate team.
|
||||
|
||||
"Anyway," David said with a blank expression. "I was about to grab lunch..."
|
||||
|
||||
He paused, and Sally just kind of stared. She was still thinking about that damn club.
|
||||
|
||||
"You want to come?" David finally said.
|
||||
|
||||
"Uh, what?" Sally began awkwardly. It took a second for her brain to process what David had just said. "Oh, yea, sure, that sounds great!", and it really *did* sound great to her, too.
|
||||
|
||||
***
|
||||
|
||||
Sally couldn't quite believe it, but David had actually given her his *phone number* after their lunch date thing. They'd walked to a nearby fast food place and both ordered a burger and fries, and, while waiting for the food to arrive, they'd talked about what both of them had started doing after finishing school.
|
||||
|
||||
Sally was sitting in her bed now and looking down at her phone, the bright screen displaying David's contact information. He'd entered his first name only, along with his phone number. For a moment, Sally wondered if he might have given her some sort of fake number, but that wouldn't make much sense, because *he* was the one who'd invited her to lunch, after all.
|
||||
|
||||
She hovered over the green call button with her thumb, considering her options. Maybe she should just text him? What would she say, though? A call just seemed easier. Plus, it was cheaper, right? With her contract and all. Finally, she tapped the button with a shaky finger.
|
||||
|
||||
"Hello?" a familiar voice said on the other end of the line.
|
||||
|
||||
"Hey, it's me, Sally, from lunch," she said awkwardly. "Do you want to go out again, maybe?"
|
||||
|
||||
Wow, that was *bold* of her, wasn't it? What had gotten into her all of a sudden? She never used to be like this with Joey, or anyone else, for that matter. She shook her head and followed up with a *super* smooth "Only if you want, though. Of course." Fucking hell.
|
||||
|
||||
"I'd love to! I'm so glad you asked," he said. "I was worried you weren't going to call."
|
||||
|
||||
He was... *worried*? That was a surprise to Sally. And a nice thing to say, too, in a weird sort of way.
|
||||
|
||||
They decided to meet up for lunch again the next day, and David picked out another fast food place in town that sold Asian takeout. Sally wasn't sure if she was going to like it, but she knew she liked *David*, and that was the main thing that mattered to her.
|
||||
|
||||
Later that night, she lay awake, staring at the ceiling, thinking about David. About how nice he'd been on the phone. About lunch. *Had* he been really nice, or had she just forgotten what talking to a nice person was like? The thought was a little depressing to her, so she dismissed it as quickly as it came. No, he *had* been very nice to her, she concluded. He was a great lunch buddy.
|
||||
|
||||
***
|
||||
|
||||
David checked himself in the mirror and pulled a face. He wet his hand in the sink and tried to smooth over a rogue curl in his otherwise silky smooth, brown hair. As he let go, the stupid thing bounced back up, and he quickly admitted defeat. *Fine*, he thought to himself with a kind of confidence that he didn't normally seem to possess. *This day will go great either way.*
|
||||
|
||||
Sally had suggested a place that he'd never been to this time around, a place that--from the images online--looked to be a small restaurant with a large outdoor seating area. For a moment, he thought to himself if maybe she picked this place because it looked romantic.
|
||||
|
||||
He shrugged off the thought as a notification made his phone vibrate in his pocket. For a second, he wondered if this was Sally canceling their date-- lunch meeting-- *friendly hangout session*.
|
||||
|
||||
It was, indeed, Sally. Evidently, she hadn't messaged him to cancel, though.
|
||||
|
||||
The little banner notification at the top of his screen captured the start of her message: *been deliberating. do you mind if we go to the thai place i talked abo...* David chuckled to himself as he tapped the notification. She'd already presented him with about seventeen choices last night, asking him which one *he* would choose. What was up with that girl?
|
||||
|
||||
*Whatever you want*, he texted back. Damn it, did that sound too disinterested? *You're choosing today*, he added. He liked the idea of doing what Sally wanted. Of seeing her happy. Of *making* her happy. Why was he so into her all of a sudden?
|
||||
|
||||
*damn it*, she texted back. *reading online now that the thai place is closed, nvm*.
|
||||
|
||||
Fair enough.
|
||||
|
||||
***
|
||||
|
||||
David looked around the big seating area to spot Sally, sitting at a far table for two, awkwardly waving at him. He waved back briefly and made his way over to her. Sitting down at the table, he asked sarcastically, "Is this the place you want to eat, or should we check out some others instead?"
|
||||
|
||||
She pulled a tiny frown and rolled her eyes. "Shut up."
|
||||
|
||||
They continued bantering as they ordered food and until after their drinks arrived. This seemed to be their rapport now: Making fun of each other over drinks and varying cuisine. It was good. No, actually. It was *great*.
|
||||
|
||||
While eating his burger (and fries with mayonnaise, of course), he looked up to meet Sally's eyes for a quick moment, who smiled back before returning her focus to her own burger, also with fries and mayo. And ketchup. *And* barbecue sauce.
|
||||
Jesus Christ.
|
||||
|
||||
He continued looking at Sally for another few seconds, studying her features, taking in her eyes, which were nestled neatly between the rims of her glasses and below her long, blonde bangs. It was warm today, and Sally was wearing a flowy, bright top and a short, blue skirt that looked like she'd just bought it the same day.
|
||||
|
||||
Sally looked back up at him. "You know," she began. "I've really been enjoying our dates."
|
||||
|
||||
*Our dates*. Did she mean their lunch meetups? Or did she really mean *dates*? He gave her the benefit of the doubt, because for him, too, it was difficult to come up with names for this... arrangement.
|
||||
|
||||
"Me too," he shot back before stuffing a couple of fries into his mouth. After he swallowed, he raised an eyebrow and asked: "Dates?"
|
||||
|
||||
She looked back up at him and smiled. "I mean, if you like. We're eating, we're talking, we're... having fun." She paused. "Isn't that what a date is?"
|
||||
|
||||
David let what that sink in for a moment. He looked at her and smiled. Of course, he admitted to himself, he'd been *hoping* that these were proper dates. And sitting across from Sally, right here, right now, *knowing* that she also thought of them as *dates*... it made him feel a sort of happiness that he hadn't felt in a long time. He quietly smiled to himself and looked down at his plate again, stuffing another handful of fries into his mouth.
|
||||
|
||||
***
|
||||
|
||||
As she arrived home and unlocked the front door, Sally realized that she'd been thinking about David, and David alone, for the last few days. Whenever she watched TV and saw a cute scene, she thought of David. When chatting with her friends about their relationships, she thought of David. And, yes, she admitted to herself, she'd also thought of David while touching herself. Once or twice.
|
||||
|
||||
But that wasn't bad, she concluded. In fact, she accepted all of it as what it was: A sign that she really liked David. She smiled to herself as she went up to her room, throwing her jacket onto a chair in the corner.
|
||||
|
||||
She let herself drop backwards onto the bed like a brick and pulled out her phone, holding it over her head. She opened her message thread with David and typed the words *Today was fun.* Then, she followed up with another message: *I really like you, David.*
|
||||
|
||||
This was, for the first time since Sally could remember, something she was absolutely certain about. She didn't have to think twice before sending those messages. She didn't even *want* to think twice about them, because it was so unusually clear to her. She liked David, and there would be nothing she could tell herself, no question she could ask herself, to change that.
|
||||
|
||||
Before he even read the message, Sally moved into her contact list with a few quick swipes, scrolling down to the entries that started with the letter J. *J*, as in *Joey*, of course. She tapped his name and immediately felt a weird sense of unease, a dread that she'd always felt when she had to think about him. She scrolled down past the phone numbers and his address until, right there, in the center of her screen, was a big red button with a trash can icon and the word *Delete* next to it.
|
||||
|
||||
She thought of the lunches with David again, the way he stuffed fries into his mouth. The way he snickered when she asked the waiter for three different condiments. The way his smooth hair dissolved into more and more curls the longer he was outside in the dry summer heat. The way things seemed so *easy* with him. All of a sudden, the dread that Joey's name brought up in her vanished, just like that.
|
||||
|
||||
And then she pressed the button.
|
||||
|
||||
As she watched Joey's name slide off-screen in the contact list, all the other J names shuffling up and down neatly to fill the gap, a banner notification came down from the top of her screen. It was David.
|
||||
|
||||
*I like you too, Sally. Really like you.*
|
||||
|
||||
Another notification came down. *Lunch again tomorrow?*
|
|
@ -1,190 +1,190 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 🎉 Vince, a Party and Brandon
|
||||
summary: "Vincent is an anxious introvert who is desperate to find a guy to have some fun with. At his best friend's party, he gets the chance to do just that, but his anxiety threatens to screw it all up."
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
mature: true
|
||||
reedsy: https://blog.reedsy.com/creative-writing-prompts/contests/104/submissions/78425/
|
||||
discuss: https://twitter.com/Ellpeck/status/1419838270909865985
|
||||
---
|
||||
|
||||
After dreading it for multiple hours now, it was finally time for Vincent to read the messages that his friend had been blowing up his phone with. It was a little difficult for him, because the conversation that he'd anxiously, but silently, opted out of was regarding the party that Myra was throwing later today. Vince rolled over in his bed and reached blindly for his phone, which he was sure had fallen onto the ground at some point in the afternoon. Unlocking it, he was immediately bombarded by about thirty-seven thousand messages from his friend.
|
||||
|
||||
**are you coming tonight**
|
||||
|
||||
**hey, stop ignorign me**
|
||||
|
||||
**read my messages you cheap ass**
|
||||
|
||||
He groaned and rolled over again, kicking the blanket onto the floor with his feet. For a moment, he considered just saying no. But he wasn't going to let himself give up that easily. Not again.
|
||||
|
||||
*i dont know ok*
|
||||
|
||||
*youre just gonna talk to someone else*
|
||||
|
||||
*and ill be all by myself*
|
||||
|
||||
The little tick marks turned blue, and his face followed suit quickly when his phone began to vibrate violently in his hand. A call? Really?
|
||||
|
||||
"If you don't come, I will literally cry, Vincent. What the fuck am I going to do without you?"
|
||||
|
||||
Myra genuinely sounded a little annoyed, but Vince knew this game: She'd pretend to be pissed at him for a minute until he started feeling genuinely bad, and then she had to explain to him that she was just joking, like always. It was less of a game and more of a *Myra being a normal friend while Vince stumbles around his inability to be a functioning person*. So, pretty much like always.
|
||||
|
||||
"Damn it, Vince, you know I'm not being serious, right?" There it was. "You're the only person who it's fun to drink with."
|
||||
|
||||
Admittedly, he *was* pretty fun when he managed to leave his anxiety behind at the bottom of a glass. And drunk Vince and drunk Myra would always start deep, meaninglessly meaningful conversations that made them think deeply and then cackle embarrassingly again and again.
|
||||
|
||||
And if he said no to this party, he would've not only denied his best friend, who was there for him pretty much constantly, but he'd just have to have another sad Saturday night consisting of chips, memes and maybe a, uh, *fun toy* and some porn. Admittedly, that sounded a lot more fun than some jock-infested party.
|
||||
|
||||
"Look, listen," Myra began after enduring the awkward silence for longer than she reasonably should have. "There's this guy coming to the party who is really sweet, and he looks pretty cute too. Dan even said that he might be, you know, *a top*, and I know how desperate you've been for that sort of thing recently."
|
||||
|
||||
Damn it. Why did Vincent tell anyone anything, ever?
|
||||
|
||||
"Why do I tell you anything, ever?" He half-whispered into his phone and sat up into a surprisingly graceful cross-legged situation and picked up the dildo that he spotted at the foot of his bed. He really had to take better care of his belongings.
|
||||
|
||||
"I'm not sure. It's weird. But no judgement, babe. I know what it's like."
|
||||
|
||||
"You literally just said that it's weird, how is that *not* judgement?"
|
||||
|
||||
"Listen. Are you coming or not? I'm not going to spend the rest of the evening getting your sad ass laid."
|
||||
|
||||
Vince rolled his eyes and sighed, deliberately loud enough for her to hear it clearly.
|
||||
|
||||
"Stop rolling your eyes at me. Yes or no?"
|
||||
|
||||
She knew him too well. He looked at the toy in his hand and fondled it a little. *Non-sexually* fondled it. He really *did* want to do stuff with a guy again, but he also quite enjoyed the idea of not having to go out and meet new people.
|
||||
|
||||
"Fuck, fine," he said and flopped back onto his back. Goddamn it.
|
||||
|
||||
"There we go," Myra exclaimed loudly and immediately hung up.
|
||||
|
||||
There we fucking go.
|
||||
|
||||
***
|
||||
|
||||
Myra's party turned out to be happening at a different house that apparently belonged to a friend of hers or something. Vince was kind of relieved, as Myra's apartment didn't feature a lot of space to hide from sweaty crowds of drunken people in. The night was unfurling as people around him started showing clear signs of a buzz, and of course, Myra was absolutely nowhere to be found. Great.
|
||||
|
||||
In his frustration, Vince decided to sit down on one of the chic living room sofas that were very clearly too expensive to house his poor ass. Nevertheless, it seemed to invite him to take a little break from the crowds and the anxiety and just *breathe* for a second.
|
||||
|
||||
If he was being honest with himself, Vincent wasn't at all interested in this party or the people at it. He sipped his drink tentatively, a vodka and coke that tasted more like a vodka and vodka with a side of coke, and looked around the bustling living room. Not only had Myra seemingly disappeared, any other people that he may know and be able to interact with were also nowhere to be found. And while this meant that there were *also* no people around that he might want to run-away-slash-hide from, it was still kind of a bummer to be wasting his night at this place and still sit around alone.
|
||||
|
||||
A few more minutes went by, and Vince started spotting one or two people that he *did* know, but none of which he wanted to talk to. There was a guy that he'd briefly hooked up with at another one of Myra's parties about a year ago (he was one of the "straight, but I have needs, too" guys), and there was a girl who had flirted with him a lot before Vince found out that he was, in fact, not at all interested in her or her gender. They'd still continue talking every now and again after that, but it seemed to Vince like she'd only been interested in him as a potential romantic (or sexual) partner, which was fair enough.
|
||||
|
||||
Myra finally reappeared by tapping Vincent on the shoulder from behind the sofa. She was radiating confidence and also, maybe, probably, a slight bit of drunkenness. Those tended to go hand in hand for her.
|
||||
|
||||
"Hey, stranger," she said to him as if they hadn't talked for, like, months, and not literally less than half an hour.
|
||||
|
||||
"Is this a rickroll situation, and you just forgot the actual lyrics, or what's going on with you?" He said to her with a snarky grin.
|
||||
|
||||
"Shut up," she said, jumped over the backrest and landed on the soft, brown leather beside him. She came a little closer and tilted her head to whisper into Vince's ear.
|
||||
|
||||
"Okay, listen. Brandon is here," she said.
|
||||
|
||||
Vince made one of his famous faces. "Who the hell is Brandon?"
|
||||
|
||||
"The guy I was telling you about! The cute one with a dick that isn't made of silicone?"
|
||||
|
||||
Ah, yes. The human dick man.
|
||||
|
||||
"Couldn't you guess from the *name*?" She laughed. He did not.
|
||||
|
||||
He chose a smooth "How much have you had to drink?" as his reply and then pushed her head off of his shoulder. "Where is he?"
|
||||
|
||||
"He's, uh..." She narrowed her eyes and began to investigate the crowd.
|
||||
|
||||
"Right there!" She exclaimed and jumped up from the couch. "Go to him! Come on!"
|
||||
|
||||
***
|
||||
|
||||
Brandon was, in fact, quite cute. Actually, Vince might have been drooling over him just a tiny bit while waiting for Myra to resurface earlier, even before he knew that he was the cute, gay friend in question. Well, he might have been bi or pan or something. That wasn't important right now.
|
||||
|
||||
What *was* important right now was getting Brandon out of the hot tub and into one of the spare bedrooms. Why was there even a *hot tub*? Had someone taken this house from a high school movie? Though, in the hot tub's defense, it did allow Vince to see Brandon's not-quite-chiseled chest and his not-so-short hair that was flowing over his surprisingly broad shoulders. He hadn't quite decided if he found Brandon cute or hot yet, but he *had* decided that he would quite enjoy spending some more time with him to figure it out.
|
||||
|
||||
Vincent, being the perfect-at-social-interaction smooth talker that he was, stood in front of the hot tub like an idiot, just staring at Brandon's beautiful fucking face. How did humans do that *speaking* thing again?
|
||||
|
||||
Brandon turned around and saw Vince standing there like an idiotic statue. He looked at him for a second and then turned to jump out of the hot tub gracefully, with little streams of water running down his chest and over his abs and dripping off of his Bermudas. That's just what water usually did, but it looked fantastic on this guy. Of course.
|
||||
|
||||
"Oh hey," Brandon began, to Vince's absolute surprise. He tried to snap out of his continued statueing and blinked. "You're Vince, right? Myra told me all about you."
|
||||
|
||||
"Yup, yea, that's... that's me. Hi." He stood there awkwardly, debating whether he should extend his hand? Go in for a hug? No, he was dripping wet. The--- *Brandon* was dripping wet. Yes.
|
||||
|
||||
Not too long after the most awkward thirty-five seconds of his life, Vince found himself sitting next to Brandon on a bed in a room that Vince was pretty sure was at least twice as big as his own apartment. Brandon had, despite Vincent's wordless disapproval, towel dried himself off and put on a shirt.
|
||||
|
||||
After staring at each other for a few seconds, their thighs rubbing together on the bed, things started going pretty fast. Brandon took of Vince's shirt and then his own, and Vincent started making use of his free hands to feel Brandon's rather muscular body. Brandon took off his Bermudas and they both realized that he was not wearing anything else underneath, revealing his rock hard---and very human---cock. Vince also took off his pants after struggling with his belt buckle for an embarrassing amount of time, and then he found himself laying on his back with Brandon's chest pressed against his, their cocks rubbing against each other. Brandon got up from the bed and grabbed Vince's legs, pulling him towards the edge of the bed.
|
||||
|
||||
Vincent knew where this was going, and he really, *really* wanted to like it. But as Brandon was pulling Vincent closer to his throbbing cock and bending his lower legs to rest them on his own shoulders, some sort of switch flicked inside Vince's head. Yes, of course he wanted to have his brains fucked out by a hot guy. By *this* hot guy. But he didn't want it right now, like this, so fast and without a single question asked.
|
||||
|
||||
Brandon was fumbling with a condom wrapper and Vincent quickly decided to use the moment to slide up a bit towards the head of the bed, taking his legs back and starting to hug them.
|
||||
|
||||
"Can we," He began. "Can we slow down a bit? I don't think I'm ready for that yet." Vincent frowned and looked at Brandon, whose expression was unreadable to him.
|
||||
|
||||
"What?" Brandon asked, still expressionless. His tone wasn't aggressive, but it wasn't all that calm, either. Had Vincent said something wrong?
|
||||
|
||||
"I thought this is what you wanted. That's what Myra said!"
|
||||
|
||||
What the fuck? Was Myra, his best friend, just going around telling random guys that Vincent was desperate to be *fucked* by some stranger stud?
|
||||
|
||||
Vincent started breathing heavily. It took a second for him to start speaking, but then he did. "Oh, and you just signed the fuck up right away, didn't you? Just ready to fuck some random guy and then never talk to him again? Is that what you do every weekend?"
|
||||
|
||||
Brandon frowned and closed his eyes. He sighed. He didn't say anything for a solid thirty seconds, which gave Vincent plenty of time to develop his famous instant regrets. Even if Brandon *was* that sort of guy, what did it matter to Vince? He *was* a little desperate to be fucked, and this stranger seemed a hell of a lot better to him than any of the other strangers at this party. And Myra had said that he was *sweet*, too. Maybe something could have happened here. But he just ruined it, officially and irrevocably. Right?
|
||||
|
||||
"Fuck," Vincent began again. He shook his head slowly and frowned. "I'm sorry, that came out wrong."
|
||||
|
||||
Brandon just stood there. "It did, didn't it?"
|
||||
|
||||
Then he walked away.
|
||||
|
||||
***
|
||||
|
||||
When Vincent trotted slowly down the stairs, the party was still in full swing, and he absolutely hated it. Not only were there a million humans that all reeked of alcohol and just generally existed, which was usually bad enough, Vincent had also ruined a very good opportunity to have sex with a very hot and, according to Myra, very sweet guy. A guy whom, even after looking around the living room and the kitchen, he wasn't able to find anywhere.
|
||||
|
||||
This was, as Vincent told himself, the perfect time to give up. Find Myra, say goodbye, and head home to his bed and his stupid toys. He didn't deserve human dick anyway, because all he could do was *be* a human dick.
|
||||
|
||||
If he talked to Myra right now, all she'd tell him would be to stop wallowing in self-pity and do something about the problem or some crap. Maybe she'd instruct him to find Brandon, or find some other guy, or apologize through text because she probably had his number, too. But Vincent wasn't ready for rationality right now. Being mad at himself felt good, in a fucked up way. And maybe it had its purpose, or at least that's what he began telling himself as he was walking outside to check the hot tub for any signs of the guy he'd just hurt for no reason.
|
||||
|
||||
Brandon was, in fact, in the hot tub. He sat there with his hands by his sides, less happy and less confident than the first time he saw him here.
|
||||
|
||||
Vincent slowly walked up to him. He closed his eyes for a second and started feeling sick to his stomach. If he was going to leave, he should leave *right now*. But that's what he usually did, and he wasn't going to mess this up again. He wanted to give this guy a chance. He wanted to give *himself* a chance, too.
|
||||
|
||||
"Hey, uh, Brandon?" He said and Brandon turned around. He narrowed his eyes as he looked into Vincent's. "Can we talk?"
|
||||
|
||||
***
|
||||
|
||||
Vincent and Brandon were sitting on a log bench at the far side of the unreasonably large backyard.
|
||||
|
||||
"Fuck, I'm so sorry," Vincent said apologetically, again. "I just... I thought about something stupid and then I snapped. I really didn't mean what I said."
|
||||
|
||||
Brandon looked at him and frowned, his eyes twitching back and forth between the ground and Vincent's face.
|
||||
|
||||
"No, you were right, man. I should have asked if you wanted to do the stuff we did. I was too fast." He didn't sound disingenuous. If anything, he sounded like he was mad at himself.
|
||||
|
||||
"I *did* want to do the stuff you did. I really wanted to. I *still* want to." After saying that, Vincent decided it was probably time to shut up. Was he being too vulnerable or honest now? Was Brandon just going to walk back to the hot tub, or go inside and fuck any of the twenty other cute guys that were less of an emotional mess than Vincent was?
|
||||
|
||||
Brandon chuckled and smiled.
|
||||
|
||||
"Okay," He said. "Let's do it, then."
|
||||
|
||||
"Wait, really?" Vincent blurted out and raised his eyebrows to the fucking sky.
|
||||
|
||||
"Yea. I still want to, too. Plus, I haven't really gotten to take a proper look at your ass yet."
|
||||
|
||||
"Hey now, I'm not *just* an ass, Brandon." Vincent said and smiled.
|
||||
|
||||
"So far, you were," Brandon whispered into his ear, and Vincent knew that it was true, but he wasn't sure if this was Brandon dirty talking or just... telling him how much of an ass he was.
|
||||
|
||||
It didn't take long until he found out, because Brandon turned Vincent's head towards his own.
|
||||
|
||||
"Can I make out with you?" He asked quietly and bit his lip.
|
||||
|
||||
"Yes," Vincent replied with a grin, and he kissed Brandon on the lips and didn't let go.
|
||||
|
||||
Eventually, their tongues were intertwined and only momentarily separated as Brandon made sure that he was doing everything exactly as Vincent wanted him to. They went slower this time, but still did all the things that they'd both wanted to do.
|
||||
|
||||
When they were done, they were both sweaty and out of breath. They cleaned themselves (and the bench) up with some tissues that Vincent found in his back pocket and kissed a final time before walking back towards the house-slash-mansion together.
|
||||
|
||||
Vincent looked at Brandon, who was walking next to him, and quietly said a genuine, vulnerable "Thanks."
|
||||
|
||||
Brandon looked back and chuckled. "It was fun." He said. Then he came a little closer.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 🎉 Vince, a Party and Brandon
|
||||
description: "Vincent is an anxious introvert who is desperate to find a guy to have some fun with. At his best friend's party, he gets the chance to do just that, but his anxiety threatens to screw it all up."
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
mature: true
|
||||
reedsy: https://blog.reedsy.com/creative-writing-prompts/contests/104/submissions/78425/
|
||||
discuss: https://twitter.com/Ellpeck/status/1419838270909865985
|
||||
---
|
||||
|
||||
After dreading it for multiple hours now, it was finally time for Vincent to read the messages that his friend had been blowing up his phone with. It was a little difficult for him, because the conversation that he'd anxiously, but silently, opted out of was regarding the party that Myra was throwing later today. Vince rolled over in his bed and reached blindly for his phone, which he was sure had fallen onto the ground at some point in the afternoon. Unlocking it, he was immediately bombarded by about thirty-seven thousand messages from his friend.
|
||||
|
||||
**are you coming tonight**
|
||||
|
||||
**hey, stop ignorign me**
|
||||
|
||||
**read my messages you cheap ass**
|
||||
|
||||
He groaned and rolled over again, kicking the blanket onto the floor with his feet. For a moment, he considered just saying no. But he wasn't going to let himself give up that easily. Not again.
|
||||
|
||||
*i dont know ok*
|
||||
|
||||
*youre just gonna talk to someone else*
|
||||
|
||||
*and ill be all by myself*
|
||||
|
||||
The little tick marks turned blue, and his face followed suit quickly when his phone began to vibrate violently in his hand. A call? Really?
|
||||
|
||||
"If you don't come, I will literally cry, Vincent. What the fuck am I going to do without you?"
|
||||
|
||||
Myra genuinely sounded a little annoyed, but Vince knew this game: She'd pretend to be pissed at him for a minute until he started feeling genuinely bad, and then she had to explain to him that she was just joking, like always. It was less of a game and more of a *Myra being a normal friend while Vince stumbles around his inability to be a functioning person*. So, pretty much like always.
|
||||
|
||||
"Damn it, Vince, you know I'm not being serious, right?" There it was. "You're the only person who it's fun to drink with."
|
||||
|
||||
Admittedly, he *was* pretty fun when he managed to leave his anxiety behind at the bottom of a glass. And drunk Vince and drunk Myra would always start deep, meaninglessly meaningful conversations that made them think deeply and then cackle embarrassingly again and again.
|
||||
|
||||
And if he said no to this party, he would've not only denied his best friend, who was there for him pretty much constantly, but he'd just have to have another sad Saturday night consisting of chips, memes and maybe a, uh, *fun toy* and some porn. Admittedly, that sounded a lot more fun than some jock-infested party.
|
||||
|
||||
"Look, listen," Myra began after enduring the awkward silence for longer than she reasonably should have. "There's this guy coming to the party who is really sweet, and he looks pretty cute too. Dan even said that he might be, you know, *a top*, and I know how desperate you've been for that sort of thing recently."
|
||||
|
||||
Damn it. Why did Vincent tell anyone anything, ever?
|
||||
|
||||
"Why do I tell you anything, ever?" He half-whispered into his phone and sat up into a surprisingly graceful cross-legged situation and picked up the dildo that he spotted at the foot of his bed. He really had to take better care of his belongings.
|
||||
|
||||
"I'm not sure. It's weird. But no judgement, babe. I know what it's like."
|
||||
|
||||
"You literally just said that it's weird, how is that *not* judgement?"
|
||||
|
||||
"Listen. Are you coming or not? I'm not going to spend the rest of the evening getting your sad ass laid."
|
||||
|
||||
Vince rolled his eyes and sighed, deliberately loud enough for her to hear it clearly.
|
||||
|
||||
"Stop rolling your eyes at me. Yes or no?"
|
||||
|
||||
She knew him too well. He looked at the toy in his hand and fondled it a little. *Non-sexually* fondled it. He really *did* want to do stuff with a guy again, but he also quite enjoyed the idea of not having to go out and meet new people.
|
||||
|
||||
"Fuck, fine," he said and flopped back onto his back. Goddamn it.
|
||||
|
||||
"There we go," Myra exclaimed loudly and immediately hung up.
|
||||
|
||||
There we fucking go.
|
||||
|
||||
***
|
||||
|
||||
Myra's party turned out to be happening at a different house that apparently belonged to a friend of hers or something. Vince was kind of relieved, as Myra's apartment didn't feature a lot of space to hide from sweaty crowds of drunken people in. The night was unfurling as people around him started showing clear signs of a buzz, and of course, Myra was absolutely nowhere to be found. Great.
|
||||
|
||||
In his frustration, Vince decided to sit down on one of the chic living room sofas that were very clearly too expensive to house his poor ass. Nevertheless, it seemed to invite him to take a little break from the crowds and the anxiety and just *breathe* for a second.
|
||||
|
||||
If he was being honest with himself, Vincent wasn't at all interested in this party or the people at it. He sipped his drink tentatively, a vodka and coke that tasted more like a vodka and vodka with a side of coke, and looked around the bustling living room. Not only had Myra seemingly disappeared, any other people that he may know and be able to interact with were also nowhere to be found. And while this meant that there were *also* no people around that he might want to run-away-slash-hide from, it was still kind of a bummer to be wasting his night at this place and still sit around alone.
|
||||
|
||||
A few more minutes went by, and Vince started spotting one or two people that he *did* know, but none of which he wanted to talk to. There was a guy that he'd briefly hooked up with at another one of Myra's parties about a year ago (he was one of the "straight, but I have needs, too" guys), and there was a girl who had flirted with him a lot before Vince found out that he was, in fact, not at all interested in her or her gender. They'd still continue talking every now and again after that, but it seemed to Vince like she'd only been interested in him as a potential romantic (or sexual) partner, which was fair enough.
|
||||
|
||||
Myra finally reappeared by tapping Vincent on the shoulder from behind the sofa. She was radiating confidence and also, maybe, probably, a slight bit of drunkenness. Those tended to go hand in hand for her.
|
||||
|
||||
"Hey, stranger," she said to him as if they hadn't talked for, like, months, and not literally less than half an hour.
|
||||
|
||||
"Is this a rickroll situation, and you just forgot the actual lyrics, or what's going on with you?" He said to her with a snarky grin.
|
||||
|
||||
"Shut up," she said, jumped over the backrest and landed on the soft, brown leather beside him. She came a little closer and tilted her head to whisper into Vince's ear.
|
||||
|
||||
"Okay, listen. Brandon is here," she said.
|
||||
|
||||
Vince made one of his famous faces. "Who the hell is Brandon?"
|
||||
|
||||
"The guy I was telling you about! The cute one with a dick that isn't made of silicone?"
|
||||
|
||||
Ah, yes. The human dick man.
|
||||
|
||||
"Couldn't you guess from the *name*?" She laughed. He did not.
|
||||
|
||||
He chose a smooth "How much have you had to drink?" as his reply and then pushed her head off of his shoulder. "Where is he?"
|
||||
|
||||
"He's, uh..." She narrowed her eyes and began to investigate the crowd.
|
||||
|
||||
"Right there!" She exclaimed and jumped up from the couch. "Go to him! Come on!"
|
||||
|
||||
***
|
||||
|
||||
Brandon was, in fact, quite cute. Actually, Vince might have been drooling over him just a tiny bit while waiting for Myra to resurface earlier, even before he knew that he was the cute, gay friend in question. Well, he might have been bi or pan or something. That wasn't important right now.
|
||||
|
||||
What *was* important right now was getting Brandon out of the hot tub and into one of the spare bedrooms. Why was there even a *hot tub*? Had someone taken this house from a high school movie? Though, in the hot tub's defense, it did allow Vince to see Brandon's not-quite-chiseled chest and his not-so-short hair that was flowing over his surprisingly broad shoulders. He hadn't quite decided if he found Brandon cute or hot yet, but he *had* decided that he would quite enjoy spending some more time with him to figure it out.
|
||||
|
||||
Vincent, being the perfect-at-social-interaction smooth talker that he was, stood in front of the hot tub like an idiot, just staring at Brandon's beautiful fucking face. How did humans do that *speaking* thing again?
|
||||
|
||||
Brandon turned around and saw Vince standing there like an idiotic statue. He looked at him for a second and then turned to jump out of the hot tub gracefully, with little streams of water running down his chest and over his abs and dripping off of his Bermudas. That's just what water usually did, but it looked fantastic on this guy. Of course.
|
||||
|
||||
"Oh hey," Brandon began, to Vince's absolute surprise. He tried to snap out of his continued statueing and blinked. "You're Vince, right? Myra told me all about you."
|
||||
|
||||
"Yup, yea, that's... that's me. Hi." He stood there awkwardly, debating whether he should extend his hand? Go in for a hug? No, he was dripping wet. The--- *Brandon* was dripping wet. Yes.
|
||||
|
||||
Not too long after the most awkward thirty-five seconds of his life, Vince found himself sitting next to Brandon on a bed in a room that Vince was pretty sure was at least twice as big as his own apartment. Brandon had, despite Vincent's wordless disapproval, towel dried himself off and put on a shirt.
|
||||
|
||||
After staring at each other for a few seconds, their thighs rubbing together on the bed, things started going pretty fast. Brandon took of Vince's shirt and then his own, and Vincent started making use of his free hands to feel Brandon's rather muscular body. Brandon took off his Bermudas and they both realized that he was not wearing anything else underneath, revealing his rock hard---and very human---cock. Vince also took off his pants after struggling with his belt buckle for an embarrassing amount of time, and then he found himself laying on his back with Brandon's chest pressed against his, their cocks rubbing against each other. Brandon got up from the bed and grabbed Vince's legs, pulling him towards the edge of the bed.
|
||||
|
||||
Vincent knew where this was going, and he really, *really* wanted to like it. But as Brandon was pulling Vincent closer to his throbbing cock and bending his lower legs to rest them on his own shoulders, some sort of switch flicked inside Vince's head. Yes, of course he wanted to have his brains fucked out by a hot guy. By *this* hot guy. But he didn't want it right now, like this, so fast and without a single question asked.
|
||||
|
||||
Brandon was fumbling with a condom wrapper and Vincent quickly decided to use the moment to slide up a bit towards the head of the bed, taking his legs back and starting to hug them.
|
||||
|
||||
"Can we," He began. "Can we slow down a bit? I don't think I'm ready for that yet." Vincent frowned and looked at Brandon, whose expression was unreadable to him.
|
||||
|
||||
"What?" Brandon asked, still expressionless. His tone wasn't aggressive, but it wasn't all that calm, either. Had Vincent said something wrong?
|
||||
|
||||
"I thought this is what you wanted. That's what Myra said!"
|
||||
|
||||
What the fuck? Was Myra, his best friend, just going around telling random guys that Vincent was desperate to be *fucked* by some stranger stud?
|
||||
|
||||
Vincent started breathing heavily. It took a second for him to start speaking, but then he did. "Oh, and you just signed the fuck up right away, didn't you? Just ready to fuck some random guy and then never talk to him again? Is that what you do every weekend?"
|
||||
|
||||
Brandon frowned and closed his eyes. He sighed. He didn't say anything for a solid thirty seconds, which gave Vincent plenty of time to develop his famous instant regrets. Even if Brandon *was* that sort of guy, what did it matter to Vince? He *was* a little desperate to be fucked, and this stranger seemed a hell of a lot better to him than any of the other strangers at this party. And Myra had said that he was *sweet*, too. Maybe something could have happened here. But he just ruined it, officially and irrevocably. Right?
|
||||
|
||||
"Fuck," Vincent began again. He shook his head slowly and frowned. "I'm sorry, that came out wrong."
|
||||
|
||||
Brandon just stood there. "It did, didn't it?"
|
||||
|
||||
Then he walked away.
|
||||
|
||||
***
|
||||
|
||||
When Vincent trotted slowly down the stairs, the party was still in full swing, and he absolutely hated it. Not only were there a million humans that all reeked of alcohol and just generally existed, which was usually bad enough, Vincent had also ruined a very good opportunity to have sex with a very hot and, according to Myra, very sweet guy. A guy whom, even after looking around the living room and the kitchen, he wasn't able to find anywhere.
|
||||
|
||||
This was, as Vincent told himself, the perfect time to give up. Find Myra, say goodbye, and head home to his bed and his stupid toys. He didn't deserve human dick anyway, because all he could do was *be* a human dick.
|
||||
|
||||
If he talked to Myra right now, all she'd tell him would be to stop wallowing in self-pity and do something about the problem or some crap. Maybe she'd instruct him to find Brandon, or find some other guy, or apologize through text because she probably had his number, too. But Vincent wasn't ready for rationality right now. Being mad at himself felt good, in a fucked up way. And maybe it had its purpose, or at least that's what he began telling himself as he was walking outside to check the hot tub for any signs of the guy he'd just hurt for no reason.
|
||||
|
||||
Brandon was, in fact, in the hot tub. He sat there with his hands by his sides, less happy and less confident than the first time he saw him here.
|
||||
|
||||
Vincent slowly walked up to him. He closed his eyes for a second and started feeling sick to his stomach. If he was going to leave, he should leave *right now*. But that's what he usually did, and he wasn't going to mess this up again. He wanted to give this guy a chance. He wanted to give *himself* a chance, too.
|
||||
|
||||
"Hey, uh, Brandon?" He said and Brandon turned around. He narrowed his eyes as he looked into Vincent's. "Can we talk?"
|
||||
|
||||
***
|
||||
|
||||
Vincent and Brandon were sitting on a log bench at the far side of the unreasonably large backyard.
|
||||
|
||||
"Fuck, I'm so sorry," Vincent said apologetically, again. "I just... I thought about something stupid and then I snapped. I really didn't mean what I said."
|
||||
|
||||
Brandon looked at him and frowned, his eyes twitching back and forth between the ground and Vincent's face.
|
||||
|
||||
"No, you were right, man. I should have asked if you wanted to do the stuff we did. I was too fast." He didn't sound disingenuous. If anything, he sounded like he was mad at himself.
|
||||
|
||||
"I *did* want to do the stuff you did. I really wanted to. I *still* want to." After saying that, Vincent decided it was probably time to shut up. Was he being too vulnerable or honest now? Was Brandon just going to walk back to the hot tub, or go inside and fuck any of the twenty other cute guys that were less of an emotional mess than Vincent was?
|
||||
|
||||
Brandon chuckled and smiled.
|
||||
|
||||
"Okay," He said. "Let's do it, then."
|
||||
|
||||
"Wait, really?" Vincent blurted out and raised his eyebrows to the fucking sky.
|
||||
|
||||
"Yea. I still want to, too. Plus, I haven't really gotten to take a proper look at your ass yet."
|
||||
|
||||
"Hey now, I'm not *just* an ass, Brandon." Vincent said and smiled.
|
||||
|
||||
"So far, you were," Brandon whispered into his ear, and Vincent knew that it was true, but he wasn't sure if this was Brandon dirty talking or just... telling him how much of an ass he was.
|
||||
|
||||
It didn't take long until he found out, because Brandon turned Vincent's head towards his own.
|
||||
|
||||
"Can I make out with you?" He asked quietly and bit his lip.
|
||||
|
||||
"Yes," Vincent replied with a grin, and he kissed Brandon on the lips and didn't let go.
|
||||
|
||||
Eventually, their tongues were intertwined and only momentarily separated as Brandon made sure that he was doing everything exactly as Vincent wanted him to. They went slower this time, but still did all the things that they'd both wanted to do.
|
||||
|
||||
When they were done, they were both sweaty and out of breath. They cleaned themselves (and the bench) up with some tissues that Vincent found in his back pocket and kissed a final time before walking back towards the house-slash-mansion together.
|
||||
|
||||
Vincent looked at Brandon, who was walking next to him, and quietly said a genuine, vulnerable "Thanks."
|
||||
|
||||
Brandon looked back and chuckled. "It was fun." He said. Then he came a little closer.
|
||||
|
||||
"Hey, Vincent," He began. "Can I take your hand?"
|
|
@ -1,91 +1,91 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 📚 My Favorite Reads of 2021
|
||||
summary: I've been using 2021 to read some more again. As it turns out, there are quite a few really good books out there. Here are some of my favorites I read in 2021.
|
||||
tags: [Reading, Featured]
|
||||
mature: true
|
||||
discuss: https://twitter.com/Ellpeck/status/1467156754194653191
|
||||
---
|
||||
|
||||
2021 has been a rough year. For all of us. I decided to use it to do some more reading again. This is a list of some of my favorite books I read this year. As you'll be able to tell pretty quickly, my main interest is very gay romance books. *What a surprise.*
|
||||
|
||||
I compiled this list by going through my [StoryGraph](https://app.thestorygraph.com/profile/ellpeck) 5⭐ reviews and picking the ones that I thought it would be most interesting to talk about. There won't be many, if any, spoilers, but I'll definitely be summarizing the plot of these books in this post and putting a few funny quotes. These also aren't in any particular order, either.
|
||||
|
||||
# 🪲 Boyfriend Material, by Alexis Hall
|
||||
[Boyfriend Material](https://app.thestorygraph.com/books/4ecc34c0-04e1-420f-a303-2a900063397e) was the first book written by Alexis Hall that I had the pleasure of reading. And I found out pretty quickly that he is an absolutely *fantastic* author. His writing is incredibly funny, but also deeply emotional and touching in certain places. It's an amazing mix.
|
||||
|
||||
Boyfriend Material is about two guys who have absolutely no business falling in love... falling in love. Luc works at a charity for some sort of beetle that has (surprisingly) little significance in the story, and Oliver is some sort of fancy lawyer-type person. Luc's friends are incredibly funny (not just their personalities, but also the way they're presented), and the way that Luc and Oliver interact is delightfully embarrassing, but also incredibly cute.
|
||||
|
||||
There's also two characters called James Royce-Royce and James Royce-Royce. I promise I'm not making that up.
|
||||
|
||||
> I met James Royce and James Royce (now James Royce-Royce and James Royce-Royce) at a university LGBTQ+ event. In some ways, it’s strange the two of them work so well together because their name is pretty much the only thing they’ve ever had in common.
|
||||
|
||||
The book is a great first step in discovering the amazing, witty and hilarious writing of Alexis Hall. There's at least three of his other books that I'd love to talk about here. I promise I won't. But actually, I will. Two more of his books are coming up.
|
||||
|
||||
# 🚇 One Last Stop, by Casey McQuiston
|
||||
[One Last Stop](https://app.thestorygraph.com/books/28386517-30cc-4ce4-bb90-9336c370a9dd) falls into a genre that I usually can't quite get myself to enjoy: Somewhat far-fetched science fiction. I'd previously read one of Casey McQuiston's books, namely [Red, White and Royal Blue](https://app.thestorygraph.com/books/d9b32ad2-41d2-4663-a19c-f65ffc7b0091) and absolutely adored it, and so I thought it was a good opportunity to discover some more of their writing.
|
||||
|
||||
One Last Stop is about a girl, whom I will refer to exclusively as Coffee Girl, who moves to a big city and immediately falls in love with a girl she meets on the train, whom I will refer to as Subway Girl. There's a bit of a problem, though: Subway Girl is *not from this time*. Spooky. She's actually stuck in the train due to some sort of time... problem that I shan't go into because, to me, it is very far from the most interesting part of the book.
|
||||
|
||||
What I enjoy most is the way that the main character struggles with this issue, and the way her emotions are depicted, not only in relation to Subway Girl, but also in relation to her hilarious queer friends, her chaotic and possibly not-very-good mother, and the ever-present dread of having to go to University instead of hanging out with the girl on the train for all eternity.
|
||||
|
||||
> “I swear to God, if a ghost kills me, I’ll haunt the shower,” Wes says. “You guys will never have hot water again.” “We don’t have hot water now,” August points out. “Fine, I’ll haunt the toilet.” “Why do you want to haunt a bathroom, man?” Isaiah asks. “It’s where people are most vulnerable,” Wes says, like it’s obvious. Isaiah frowns thoughtfully and nods.
|
||||
|
||||
Please read this book, *especially* if you enjoy the sci-fi aspect more than me. Which I'm sure you do, given I ignored it as best I could.
|
||||
|
||||
# 🕍 Jews Don't Count, by David Baddiel
|
||||
[Jews Don't Count](https://app.thestorygraph.com/books/e13bcb3b-a0ea-474e-8259-e55d1b0fe4ef) is the only non-fiction book on this list, because it turns out that I enjoy fiction far more, given it's usually a lot less depressing.
|
||||
|
||||
Now, I'm not jewish. I feel the need to point this out right off the bat because I'm not a big fan of talking about political problems that I don't have any personal experience with. That being said, I *am* from Germany, and the troubles surrounding antisemitism have been absolutely drilled into our heads as schoolchildren. Even moreso did it make me feel very uncomfortable about my own observation skills, as well as my own (lack of) political interest in this topic, that this book proves that antisemitism goes mostly ignored when it comes to debate around racism, religious freedom and cultural identity.
|
||||
|
||||
If you want to educate yourself on political topics that you don't have much personal experience with (as you should!), Jews Don't Count is a great read. It's aimed at leftists like me and probably you, and it aims to shine a light on the way that antisemitism is treated in the Western world in the current times. As it turns out: It's treated very poorly. The book, however, treats the topic it's about with respect, brings up a lot of current day examples to illustrate the issues, and is only about 150 pages long, making it deliver a very quick, but also very powerful, message.
|
||||
|
||||
# 🎂 Rosaline Palmer Takes the Cake, by Alexis Hall
|
||||
I've talked about Alexis Hall before. In fact, it was this very blog post. Just... a few minutes ago, actually. But here I am, yet again, talking about his absolutely brilliant writing.
|
||||
|
||||
[The book](https://app.thestorygraph.com/books/bbac9ac1-8d25-4413-8cbd-acb82e79cb67), whose title is far too long, is about Rosaline Palmer, a bisexual single mother who makes the terrible (but great) decision of joining what is essentially a not-so-trademarked version of the British Bake-Off, only with exactly the same amount of chaos and hilarity. When that isn't currently the main thing messing up her life, it's also about her relationship with a very, uh, *lovely* man, the relationship with her daughter, and the relationship with her excellent and sexy friend Anvita (her words, not mine).
|
||||
|
||||
Here's a lot of quotes, because *Jesus Christ, this book is funny*. But also very real. I'm not quoting the real parts, because they're not as funny. But it gets very emotional, and very "there's a lot of problems with the way bisexuality is perceived by straight people", and very "life is hard sometimes". But this is just some funny parts. Don't wanna bring you down.
|
||||
|
||||
> Grace Forsythe tried to give her a reassuring look from the opposite side of a cake that was rapidly turning into a landslide. “It’s fine. I’ll just stand here holding it for the rest of my life. You can tell the judges I’m an especially elaborate fondant decoration. Which, now I think about it, is what my ex-girlfriend used to call me.”
|
||||
|
||||
> To her horror, she was actually crying. And the next thing she knew, Grace Forsythe was gently removing the spoon from her hands. “Fuck shit piss wank bollocks drink Coca-Cola buy Smeg ovens legalise cannabis abolish the monarchy. Oh sorry, did I ruin the segment? What a shame. Maybe go film someone else for a bit.” The producer and camera operator dutifully departed. Rosaline drew in a shaky breath and wiped her eyes. “God, thank you.”
|
||||
|
||||
Hi Alexis, if you're somehow reading this: I am *begging you* to make a second book that is just about Grace Forsythe and her life. Please. I'll do anything.
|
||||
|
||||
# 🏨 Act Your Age, Eve Brown, by Talia Hibbert
|
||||
Talia Hibbert is also one of my favorite authors. She writes brilliantly about diverse people, be that sexuality, race, personality or illnesses. Out of the three Brown Sisters books, [Act Your Age, Eve Brown](https://app.thestorygraph.com/books/8a97c89d-1436-4563-bc1f-e44836a750b9) is by far my favorite.
|
||||
|
||||
Act Your Age, Eve Brown is about Eve Brown, who stumbles into a... hotel-slash-inn ran by a particularly charming, but also (to her) extremely irritating, young man named Jacob. As it turns out, Jacob doesn't quite like Eve either... *at first*. If you know what I mean.
|
||||
|
||||
The book is written from both perspectives on a per-scene and per-chapter basis, and it is a fantastic read. The relationship between the two main characters is hilarious, and with Eve actually *getting a job* from the very guy whom she *ran over* with her car (yes, really), it is quite the rollercoaster, to say the least.
|
||||
|
||||
Also, the writing is hilarious. Just look.
|
||||
|
||||
> Jacob Wayne was never screwed. Well, not like that—obviously he was sometimes screwed in other, better ways. Although not as often as he’d like, but—you know—ah, fuck it, never mind.
|
||||
|
||||
> There was that voice again, strange and yet familiar. His mind was hot and sticky like fudge. Yum, fudge. Was this a guest, maybe? A yummy, fudgy guest? Fuck. No lying around in the street in front of guests. It was inappropriate and irresponsible and very bad business.
|
||||
|
||||
Yum, fudge.
|
||||
|
||||
# 🔎 Murder Most Actual, by Alexis Hall
|
||||
[Murder Most Actual](https://app.thestorygraph.com/books/3f146f4d-136e-4c75-9cd7-4bdd50aa25b3) is the last of these books I read. It's by Alexis Hall, whom you may have heard of from the last seventeen thousand times I talked about him. He's brilliant, blah blah blah, you've heard this already, but what you haven't heard yet is the fact that I downloaded an e-book from a site I'd never used before, made an account and everything, and then painstakingly shoved it onto my Kindle, so I could read it. As it turns out, it was worth it. Very. In fact, this is probably his best book yet. Maybe. I'm not sure.
|
||||
|
||||
Murder Most Actual is about murder, but in a most actual way. Yes. It follows a couple of lesbians (as in "a lesbian couple", not, like, 3 stray lesbians), because everyone in Alexis Hall's books is gay (which is not criticism, it's exactly the way I want it to be), as they arrive at a hotel that is hosting a fun murder mystery dinner. The only problem is that it's not so much a murder mystery dinner as *multiple murders*, *multiple mysteries* and an ever-growing shortness of dinner. Over the course of the book, the relationship between the two main characters redevelops into something absolutely adorable, and they also solve the murders. Somewhat. With the help of a particularly disgruntled police guy, who I think should also get his own spin-off eventually.
|
||||
|
||||
It's also, and I know I'm starting to sound like I'm repeating myself, *incredibly funny*. Getting these quotes onto my computer was an absolute nightmare, by the way, becasue the notes and highlighted sections from my Kindle don't sync with my computer because it's not a... proper Kindle... Amazon... book. Thing.
|
||||
|
||||
> Liza was suddenly aware of an absence at her side as Hanna stepped forward to join the free-for-all. “Just a wacky, out-there suggestion somebody might want to jump on. Could we, maybe, call the police?”
|
||||
|
||||
> Now Sir Richard was looking genuinely crestfallen. “You know, between the two of you, you’re almost taking all the fun out of this.” “Out of the dead man?” Hanna clarified.
|
||||
|
||||
> Neither the professor nor the killer had been courteous enough to wear shoes that were notably large or small, or characterised with a distinctive tread, or perhaps conveniently embossed with the name of a manufacturer who only ever made three pairs of shoes a year for a very select list of clients.
|
||||
|
||||
Also, I love Hanna. Just wanted to say that. *Also*, each chapter has a fun Clue(do)-style title with a person, and an object, and a location. It's great. I love it.
|
||||
|
||||
# So Yea,
|
||||
I think the main thing we learn from this list is that I love romantic fiction, and I love Alexis Hall. I'm sorry, it's just all so good.
|
||||
|
||||
Anyway, I hope this post was interesting to at least a small subset of you. I know that this isn't what I regularly talk about, and this post contains a surprising lack of programming-related things (there you go, now it contains programming-related things, sort of), but reading is also something I really enjoy doing. Although I do have to admit that I'm not very good at doing it consistently.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 📚 My Favorite Reads of 2021
|
||||
description: I've been using 2021 to read some more again. As it turns out, there are quite a few really good books out there. Here are some of my favorites I read in 2021.
|
||||
tags: [Reading, Featured]
|
||||
mature: true
|
||||
discuss: https://twitter.com/Ellpeck/status/1467156754194653191
|
||||
---
|
||||
|
||||
2021 has been a rough year. For all of us. I decided to use it to do some more reading again. This is a list of some of my favorite books I read this year. As you'll be able to tell pretty quickly, my main interest is very gay romance books. *What a surprise.*
|
||||
|
||||
I compiled this list by going through my [StoryGraph](https://app.thestorygraph.com/profile/ellpeck) 5⭐ reviews and picking the ones that I thought it would be most interesting to talk about. There won't be many, if any, spoilers, but I'll definitely be summarizing the plot of these books in this post and putting a few funny quotes. These also aren't in any particular order, either.
|
||||
|
||||
# 🪲 Boyfriend Material, by Alexis Hall
|
||||
[Boyfriend Material](https://app.thestorygraph.com/books/4ecc34c0-04e1-420f-a303-2a900063397e) was the first book written by Alexis Hall that I had the pleasure of reading. And I found out pretty quickly that he is an absolutely *fantastic* author. His writing is incredibly funny, but also deeply emotional and touching in certain places. It's an amazing mix.
|
||||
|
||||
Boyfriend Material is about two guys who have absolutely no business falling in love... falling in love. Luc works at a charity for some sort of beetle that has (surprisingly) little significance in the story, and Oliver is some sort of fancy lawyer-type person. Luc's friends are incredibly funny (not just their personalities, but also the way they're presented), and the way that Luc and Oliver interact is delightfully embarrassing, but also incredibly cute.
|
||||
|
||||
There's also two characters called James Royce-Royce and James Royce-Royce. I promise I'm not making that up.
|
||||
|
||||
> I met James Royce and James Royce (now James Royce-Royce and James Royce-Royce) at a university LGBTQ+ event. In some ways, it’s strange the two of them work so well together because their name is pretty much the only thing they’ve ever had in common.
|
||||
|
||||
The book is a great first step in discovering the amazing, witty and hilarious writing of Alexis Hall. There's at least three of his other books that I'd love to talk about here. I promise I won't. But actually, I will. Two more of his books are coming up.
|
||||
|
||||
# 🚇 One Last Stop, by Casey McQuiston
|
||||
[One Last Stop](https://app.thestorygraph.com/books/28386517-30cc-4ce4-bb90-9336c370a9dd) falls into a genre that I usually can't quite get myself to enjoy: Somewhat far-fetched science fiction. I'd previously read one of Casey McQuiston's books, namely [Red, White and Royal Blue](https://app.thestorygraph.com/books/d9b32ad2-41d2-4663-a19c-f65ffc7b0091) and absolutely adored it, and so I thought it was a good opportunity to discover some more of their writing.
|
||||
|
||||
One Last Stop is about a girl, whom I will refer to exclusively as Coffee Girl, who moves to a big city and immediately falls in love with a girl she meets on the train, whom I will refer to as Subway Girl. There's a bit of a problem, though: Subway Girl is *not from this time*. Spooky. She's actually stuck in the train due to some sort of time... problem that I shan't go into because, to me, it is very far from the most interesting part of the book.
|
||||
|
||||
What I enjoy most is the way that the main character struggles with this issue, and the way her emotions are depicted, not only in relation to Subway Girl, but also in relation to her hilarious queer friends, her chaotic and possibly not-very-good mother, and the ever-present dread of having to go to University instead of hanging out with the girl on the train for all eternity.
|
||||
|
||||
> “I swear to God, if a ghost kills me, I’ll haunt the shower,” Wes says. “You guys will never have hot water again.” “We don’t have hot water now,” August points out. “Fine, I’ll haunt the toilet.” “Why do you want to haunt a bathroom, man?” Isaiah asks. “It’s where people are most vulnerable,” Wes says, like it’s obvious. Isaiah frowns thoughtfully and nods.
|
||||
|
||||
Please read this book, *especially* if you enjoy the sci-fi aspect more than me. Which I'm sure you do, given I ignored it as best I could.
|
||||
|
||||
# 🕍 Jews Don't Count, by David Baddiel
|
||||
[Jews Don't Count](https://app.thestorygraph.com/books/e13bcb3b-a0ea-474e-8259-e55d1b0fe4ef) is the only non-fiction book on this list, because it turns out that I enjoy fiction far more, given it's usually a lot less depressing.
|
||||
|
||||
Now, I'm not jewish. I feel the need to point this out right off the bat because I'm not a big fan of talking about political problems that I don't have any personal experience with. That being said, I *am* from Germany, and the troubles surrounding antisemitism have been absolutely drilled into our heads as schoolchildren. Even moreso did it make me feel very uncomfortable about my own observation skills, as well as my own (lack of) political interest in this topic, that this book proves that antisemitism goes mostly ignored when it comes to debate around racism, religious freedom and cultural identity.
|
||||
|
||||
If you want to educate yourself on political topics that you don't have much personal experience with (as you should!), Jews Don't Count is a great read. It's aimed at leftists like me and probably you, and it aims to shine a light on the way that antisemitism is treated in the Western world in the current times. As it turns out: It's treated very poorly. The book, however, treats the topic it's about with respect, brings up a lot of current day examples to illustrate the issues, and is only about 150 pages long, making it deliver a very quick, but also very powerful, message.
|
||||
|
||||
# 🎂 Rosaline Palmer Takes the Cake, by Alexis Hall
|
||||
I've talked about Alexis Hall before. In fact, it was this very blog post. Just... a few minutes ago, actually. But here I am, yet again, talking about his absolutely brilliant writing.
|
||||
|
||||
[The book](https://app.thestorygraph.com/books/bbac9ac1-8d25-4413-8cbd-acb82e79cb67), whose title is far too long, is about Rosaline Palmer, a bisexual single mother who makes the terrible (but great) decision of joining what is essentially a not-so-trademarked version of the British Bake-Off, only with exactly the same amount of chaos and hilarity. When that isn't currently the main thing messing up her life, it's also about her relationship with a very, uh, *lovely* man, the relationship with her daughter, and the relationship with her excellent and sexy friend Anvita (her words, not mine).
|
||||
|
||||
Here's a lot of quotes, because *Jesus Christ, this book is funny*. But also very real. I'm not quoting the real parts, because they're not as funny. But it gets very emotional, and very "there's a lot of problems with the way bisexuality is perceived by straight people", and very "life is hard sometimes". But this is just some funny parts. Don't wanna bring you down.
|
||||
|
||||
> Grace Forsythe tried to give her a reassuring look from the opposite side of a cake that was rapidly turning into a landslide. “It’s fine. I’ll just stand here holding it for the rest of my life. You can tell the judges I’m an especially elaborate fondant decoration. Which, now I think about it, is what my ex-girlfriend used to call me.”
|
||||
|
||||
> To her horror, she was actually crying. And the next thing she knew, Grace Forsythe was gently removing the spoon from her hands. “Fuck shit piss wank bollocks drink Coca-Cola buy Smeg ovens legalise cannabis abolish the monarchy. Oh sorry, did I ruin the segment? What a shame. Maybe go film someone else for a bit.” The producer and camera operator dutifully departed. Rosaline drew in a shaky breath and wiped her eyes. “God, thank you.”
|
||||
|
||||
Hi Alexis, if you're somehow reading this: I am *begging you* to make a second book that is just about Grace Forsythe and her life. Please. I'll do anything.
|
||||
|
||||
# 🏨 Act Your Age, Eve Brown, by Talia Hibbert
|
||||
Talia Hibbert is also one of my favorite authors. She writes brilliantly about diverse people, be that sexuality, race, personality or illnesses. Out of the three Brown Sisters books, [Act Your Age, Eve Brown](https://app.thestorygraph.com/books/8a97c89d-1436-4563-bc1f-e44836a750b9) is by far my favorite.
|
||||
|
||||
Act Your Age, Eve Brown is about Eve Brown, who stumbles into a... hotel-slash-inn ran by a particularly charming, but also (to her) extremely irritating, young man named Jacob. As it turns out, Jacob doesn't quite like Eve either... *at first*. If you know what I mean.
|
||||
|
||||
The book is written from both perspectives on a per-scene and per-chapter basis, and it is a fantastic read. The relationship between the two main characters is hilarious, and with Eve actually *getting a job* from the very guy whom she *ran over* with her car (yes, really), it is quite the rollercoaster, to say the least.
|
||||
|
||||
Also, the writing is hilarious. Just look.
|
||||
|
||||
> Jacob Wayne was never screwed. Well, not like that—obviously he was sometimes screwed in other, better ways. Although not as often as he’d like, but—you know—ah, fuck it, never mind.
|
||||
|
||||
> There was that voice again, strange and yet familiar. His mind was hot and sticky like fudge. Yum, fudge. Was this a guest, maybe? A yummy, fudgy guest? Fuck. No lying around in the street in front of guests. It was inappropriate and irresponsible and very bad business.
|
||||
|
||||
Yum, fudge.
|
||||
|
||||
# 🔎 Murder Most Actual, by Alexis Hall
|
||||
[Murder Most Actual](https://app.thestorygraph.com/books/3f146f4d-136e-4c75-9cd7-4bdd50aa25b3) is the last of these books I read. It's by Alexis Hall, whom you may have heard of from the last seventeen thousand times I talked about him. He's brilliant, blah blah blah, you've heard this already, but what you haven't heard yet is the fact that I downloaded an e-book from a site I'd never used before, made an account and everything, and then painstakingly shoved it onto my Kindle, so I could read it. As it turns out, it was worth it. Very. In fact, this is probably his best book yet. Maybe. I'm not sure.
|
||||
|
||||
Murder Most Actual is about murder, but in a most actual way. Yes. It follows a couple of lesbians (as in "a lesbian couple", not, like, 3 stray lesbians), because everyone in Alexis Hall's books is gay (which is not criticism, it's exactly the way I want it to be), as they arrive at a hotel that is hosting a fun murder mystery dinner. The only problem is that it's not so much a murder mystery dinner as *multiple murders*, *multiple mysteries* and an ever-growing shortness of dinner. Over the course of the book, the relationship between the two main characters redevelops into something absolutely adorable, and they also solve the murders. Somewhat. With the help of a particularly disgruntled police guy, who I think should also get his own spin-off eventually.
|
||||
|
||||
It's also, and I know I'm starting to sound like I'm repeating myself, *incredibly funny*. Getting these quotes onto my computer was an absolute nightmare, by the way, becasue the notes and highlighted sections from my Kindle don't sync with my computer because it's not a... proper Kindle... Amazon... book. Thing.
|
||||
|
||||
> Liza was suddenly aware of an absence at her side as Hanna stepped forward to join the free-for-all. “Just a wacky, out-there suggestion somebody might want to jump on. Could we, maybe, call the police?”
|
||||
|
||||
> Now Sir Richard was looking genuinely crestfallen. “You know, between the two of you, you’re almost taking all the fun out of this.” “Out of the dead man?” Hanna clarified.
|
||||
|
||||
> Neither the professor nor the killer had been courteous enough to wear shoes that were notably large or small, or characterised with a distinctive tread, or perhaps conveniently embossed with the name of a manufacturer who only ever made three pairs of shoes a year for a very select list of clients.
|
||||
|
||||
Also, I love Hanna. Just wanted to say that. *Also*, each chapter has a fun Clue(do)-style title with a person, and an object, and a location. It's great. I love it.
|
||||
|
||||
# So Yea,
|
||||
I think the main thing we learn from this list is that I love romantic fiction, and I love Alexis Hall. I'm sorry, it's just all so good.
|
||||
|
||||
Anyway, I hope this post was interesting to at least a small subset of you. I know that this isn't what I regularly talk about, and this post contains a surprising lack of programming-related things (there you go, now it contains programming-related things, sort of), but reading is also something I really enjoy doing. Although I do have to admit that I'm not very good at doing it consistently.
|
||||
|
||||
Either way, thanks so much for reading, and if you're Alexis Hall, please write more books. No pressure, though.
|
|
@ -1,66 +1,66 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 💻 Your Minecraft Modding Questions, Answered
|
||||
summary: I asked yall to send me your modding and programming questions on Twitter and Discord, and in this post, I try to answer all of those.
|
||||
tags: [Minecraft, Featured]
|
||||
discuss: https://twitter.com/Ellpeck/status/1373660751060160512
|
||||
---
|
||||
|
||||
Hi, I'm Ellpeck. I'm the creator of a bunch of Minecraft mods, including Actually Additions, Nature's Aura and Pretty Pipes. A while ago, I also started taking [commissions](https://ellpeck.de/commissions), so the list of Minecraft mods I've created is slowly, but surely, growing.
|
||||
|
||||
I asked all of you on Twitter and in [my Discord server](https://ellpeck.de/discord) if there are any modding and programming-related questions you'd like me to answer. Since most of the questions yall ended up asking were related to Minecraft modding, I thought I'd make the post exclusively about that after all. It also means that you might find this post interesting even if you don't program or make Minecraft mods yourself, because the questions ended up being pretty general.
|
||||
|
||||
Here goes.
|
||||
|
||||
# How do you keep yourself interested
|
||||
> ...in an idea or project, so you won't abandon it after two days of enjoying it? (canitzp)
|
||||
|
||||
Hahaaa. I really wish I had an answer for that. I have *countless* abandoned projects, as do most people that work in creative fields in some capacity. I recently made most of them public on my [GitHub](https://github.com/ellpeck), so if you go there and scroll back far enough, you'll find some old games and unfinished mods.
|
||||
|
||||
So how *do* I keep myself interested? After all, I've made and finished a bunch of stuff. Since I suffer pretty massively from depression and anxiety, it's especially hard for me to commit and pull through on anything, really. However, there's a huge thing I've learned: If you start losing motivation for something, *don't* try to fight it. If you do, you'll just force yourself to work on the project without actually being interested, causing you to burn out with it even more. Instead, accept that you're losing interest and move on to something else. While the first strategy has lead me to abandon projects entirely several times, the latter only caused me to take fairly long breaks, but so far, I've always returned to projects that I didn't try to push myself to work on.
|
||||
|
||||
# Good tips before diving into modded Minecraft?
|
||||
> (Afkman57)
|
||||
|
||||
I'm not sure if you mean *playing* modded Minecraft or *creating* mods, so I'll just answer the question for both!
|
||||
|
||||
Before diving into *playing*, I think it's really important to know what you're getting yourself into, because expectations can pretty drastically change your experience of things. (Most) Minecraft mods are *not* commercial products, and they *don't* have quality control. Authors don't get paid for creating mods, and they don't *owe* you anything just because you downloaded their mods. I think this is very important to realize because I've interacted with so many people before that think if you download a mod, it's like you're buying a product with the promise of life-long support. If something breaks in a certain way, or something works in a way that you dislike, but the mod's author doesn't agree with what you see as a problem, they have *no* obligation to change it for you. On the other hand, modded Minecraft can be *incredibly* fun. With well-made mods, there is so much new stuff to discover and create that it feels like you got yourself an entirely different, new game.
|
||||
|
||||
Before diving into *creating mods*... well. The most important piece of advice I personally have for you is: **Learn the language first**. If you're creating mods for Java Edition, *please* have at least a basic understanding of Java first. The first time I tried my hand at programming was for a Minecraft mod (Actually Additions' sort of roots, actually) and it went horribly, because I didn't understand what was part of the language I was using and what was part of the rather complex Minecraft and Forge API. For example, because Minecraft makes heavy use of method chaining[^1], when I first started out, I used to think that that was just an inherent property of the language (which obviously makes very little sense). I don't know if that was just me being a bit slow, or if that's the kind of misunderstanding that comes from not really learning a language before diving head-first into a project that uses it.
|
||||
|
||||
# Maybe some good guidelines
|
||||
> ...on code-format or even conventions for forge-modding. (Afkman57)
|
||||
|
||||
Oh boy. Talking about conventions is always a tough one, because people disagree so fundamentally on what is good code and what isn't. A great example was when I learned that, in professional software engineering, early returns[^2] are apparently considered "bad practice" because they "decrease readability." How decreasing the amount of nesting (and thus, the amount you have to scroll to the right by) also decreases *readability*, when I think it massively *increases* readability, I'm not sure. Maybe that was just my software engineering professor having a field day, though. I really hope it's that.
|
||||
|
||||
When it comes to programming in languages that don't *rely* on formatting for their syntax (like Python), the actual formatting you use doesn't matter, even though some people might have you believe that it's *extremely important* to put opening braces on a new line. For me, the only important thing is that **you keep it consistent**. If you use an IDE, your best bet is to configure its auto-formatter exactly the way you like, and then using the format button every now and again (or even turning on format on save!) to make sure that, no matter how horrible your formatting is, at least it's consistently so.
|
||||
|
||||
# Any useful tools, resources, utilities etc.
|
||||
> ...for modding would be good too. (Afkman57)
|
||||
|
||||
I think the best, and most important tool, for modding, and any kind of programming, is a git server, be it GitHub, Bitbucket or whatever else. Source control is amazing, because not only does it allow you to see exactly what you (and your colleagues) changed an when, but it also allows you to revert any of your changes or merge them together.
|
||||
|
||||
The other very useful thing about git websites like GitHub is that you can *look at other people's code* and take it as an implicit sort of tutorial. There are countless times where I looked at the code of other, bigger mods in an attempt to find useful information on how to realize certain things in my own mods. In the very first version of Actually Additions that had [Laser Relays](https://ellpeck.de/actaddmanual/#laserRelays), they were pretty much an exact copy of [Immersive Engineering](https://www.curseforge.com/minecraft/mc-mods/immersive-engineering)'s wire system, in terms of their inner workings. When you look at and especially copy other people's code, though, make sure of two things:
|
||||
- *Understand* the code you're copying. If you don't understand it, you might as well just be mindlessly copying random code from random places.
|
||||
- Keep the code's *license* in mind. Some licenses allow you to copy code freely, some require you to give credit and some don't allow you to copy any code at all. Even if a project allows you to copy code without giving credit, it's always good practice to do so anyway.
|
||||
|
||||
# How much work did it take to make Actually Additions
|
||||
> ...from start to finish? Also how long did it take you to go from an idea to a first "prototype"? (Spo0ok)
|
||||
|
||||
This is an incredibly tough question, because of course I didn't record an exact measurement of how many hours I sunk into creating Actually Additions. What I do know, however, is this: It look *a long time*. Actually Additions was one of my first mods, and as previously discussed, I was not very good at any kind of programming when I started out, so I made al ot of mistakes, and I copied a lot of code without understanding it. That being said, I can give a rough estimate based on data that I already discussed in my [post about its features](https://ellpeck.de/blog/actually_additions).
|
||||
|
||||
The first file I uploaded to CurseForge was [this one](https://www.curseforge.com/minecraft/mc-mods/actually-additions/files/2229705), on *March 15, 2015*. I know that, before I started uploading the mod to CurseForge, I had a Minecraft Forum page (it was still that time in 2015), and I would release early versions of the mod on Mediafire or some other site. That wouldn't have lasted that long, though, and looking at the commit history for the mod, the first time I referred to it as Actually Additions wasn't long after the repository was first created, [in March 2015](https://github.com/Ellpeck/ActuallyAdditions/commit/2a2308c0ce35fe8a5ac9dcea100b9aeb941c495a). I made my last real contribution [in June 2017](https://github.com/Ellpeck/ActuallyAdditions/commits/main?after=896a082d747a3e19755ded1973544d59fa992787+244).
|
||||
|
||||
That means, to create all of the features that the mod currently has, it took me about two years. I know that measurement is pretty reasonable, because I took almost no breaks when I first created the mod. This information also means that I have now *not* worked on the mod for longer than I originally *did* work on it. It's been like that for a long while actually, because 2017 is surprisingly far in the past. That's honestly kind of scary. I'm getting old, aren't I?
|
||||
|
||||
---
|
||||
|
||||
So yea, that's about it in terms of modding-related questions. I hope you found this post enjoyable. If you did, and if you have more questions for me to answer, you can always reply to the discussion tweet linked right at the end of this post, and if there are enough additional questions, I might make a second one.
|
||||
|
||||
Anyway, thanks for reading! ❤
|
||||
|
||||
---
|
||||
|
||||
[^1]: Method chaining is a concept that is used in a few languages, but especially Java. The idea is that, when you create non-static methods that change certain properties about an object, you make the method return *the object itself*. This allows for multiple method calls to be done in one line, which is especially useful when creating a system where you apply a bunch of settings to an object. `new Block().setHardness(3).setLightLevel(15);`
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 💻 Your Minecraft Modding Questions, Answered
|
||||
description: I asked yall to send me your modding and programming questions on Twitter and Discord, and in this post, I try to answer all of those.
|
||||
tags: [Minecraft, Featured]
|
||||
discuss: https://twitter.com/Ellpeck/status/1373660751060160512
|
||||
---
|
||||
|
||||
Hi, I'm Ellpeck. I'm the creator of a bunch of Minecraft mods, including Actually Additions, Nature's Aura and Pretty Pipes. A while ago, I also started taking [commissions](https://ellpeck.de/commissions), so the list of Minecraft mods I've created is slowly, but surely, growing.
|
||||
|
||||
I asked all of you on Twitter and in [my Discord server](https://ellpeck.de/discord) if there are any modding and programming-related questions you'd like me to answer. Since most of the questions yall ended up asking were related to Minecraft modding, I thought I'd make the post exclusively about that after all. It also means that you might find this post interesting even if you don't program or make Minecraft mods yourself, because the questions ended up being pretty general.
|
||||
|
||||
Here goes.
|
||||
|
||||
# How do you keep yourself interested
|
||||
> ...in an idea or project, so you won't abandon it after two days of enjoying it? (canitzp)
|
||||
|
||||
Hahaaa. I really wish I had an answer for that. I have *countless* abandoned projects, as do most people that work in creative fields in some capacity. I recently made most of them public on my [GitHub](https://github.com/ellpeck), so if you go there and scroll back far enough, you'll find some old games and unfinished mods.
|
||||
|
||||
So how *do* I keep myself interested? After all, I've made and finished a bunch of stuff. Since I suffer pretty massively from depression and anxiety, it's especially hard for me to commit and pull through on anything, really. However, there's a huge thing I've learned: If you start losing motivation for something, *don't* try to fight it. If you do, you'll just force yourself to work on the project without actually being interested, causing you to burn out with it even more. Instead, accept that you're losing interest and move on to something else. While the first strategy has lead me to abandon projects entirely several times, the latter only caused me to take fairly long breaks, but so far, I've always returned to projects that I didn't try to push myself to work on.
|
||||
|
||||
# Good tips before diving into modded Minecraft?
|
||||
> (Afkman57)
|
||||
|
||||
I'm not sure if you mean *playing* modded Minecraft or *creating* mods, so I'll just answer the question for both!
|
||||
|
||||
Before diving into *playing*, I think it's really important to know what you're getting yourself into, because expectations can pretty drastically change your experience of things. (Most) Minecraft mods are *not* commercial products, and they *don't* have quality control. Authors don't get paid for creating mods, and they don't *owe* you anything just because you downloaded their mods. I think this is very important to realize because I've interacted with so many people before that think if you download a mod, it's like you're buying a product with the promise of life-long support. If something breaks in a certain way, or something works in a way that you dislike, but the mod's author doesn't agree with what you see as a problem, they have *no* obligation to change it for you. On the other hand, modded Minecraft can be *incredibly* fun. With well-made mods, there is so much new stuff to discover and create that it feels like you got yourself an entirely different, new game.
|
||||
|
||||
Before diving into *creating mods*... well. The most important piece of advice I personally have for you is: **Learn the language first**. If you're creating mods for Java Edition, *please* have at least a basic understanding of Java first. The first time I tried my hand at programming was for a Minecraft mod (Actually Additions' sort of roots, actually) and it went horribly, because I didn't understand what was part of the language I was using and what was part of the rather complex Minecraft and Forge API. For example, because Minecraft makes heavy use of method chaining[^1], when I first started out, I used to think that that was just an inherent property of the language (which obviously makes very little sense). I don't know if that was just me being a bit slow, or if that's the kind of misunderstanding that comes from not really learning a language before diving head-first into a project that uses it.
|
||||
|
||||
# Maybe some good guidelines
|
||||
> ...on code-format or even conventions for forge-modding. (Afkman57)
|
||||
|
||||
Oh boy. Talking about conventions is always a tough one, because people disagree so fundamentally on what is good code and what isn't. A great example was when I learned that, in professional software engineering, early returns[^2] are apparently considered "bad practice" because they "decrease readability." How decreasing the amount of nesting (and thus, the amount you have to scroll to the right by) also decreases *readability*, when I think it massively *increases* readability, I'm not sure. Maybe that was just my software engineering professor having a field day, though. I really hope it's that.
|
||||
|
||||
When it comes to programming in languages that don't *rely* on formatting for their syntax (like Python), the actual formatting you use doesn't matter, even though some people might have you believe that it's *extremely important* to put opening braces on a new line. For me, the only important thing is that **you keep it consistent**. If you use an IDE, your best bet is to configure its auto-formatter exactly the way you like, and then using the format button every now and again (or even turning on format on save!) to make sure that, no matter how horrible your formatting is, at least it's consistently so.
|
||||
|
||||
# Any useful tools, resources, utilities etc.
|
||||
> ...for modding would be good too. (Afkman57)
|
||||
|
||||
I think the best, and most important tool, for modding, and any kind of programming, is a git server, be it GitHub, Bitbucket or whatever else. Source control is amazing, because not only does it allow you to see exactly what you (and your colleagues) changed an when, but it also allows you to revert any of your changes or merge them together.
|
||||
|
||||
The other very useful thing about git websites like GitHub is that you can *look at other people's code* and take it as an implicit sort of tutorial. There are countless times where I looked at the code of other, bigger mods in an attempt to find useful information on how to realize certain things in my own mods. In the very first version of Actually Additions that had [Laser Relays](https://ellpeck.de/actaddmanual/#laserRelays), they were pretty much an exact copy of [Immersive Engineering](https://www.curseforge.com/minecraft/mc-mods/immersive-engineering)'s wire system, in terms of their inner workings. When you look at and especially copy other people's code, though, make sure of two things:
|
||||
- *Understand* the code you're copying. If you don't understand it, you might as well just be mindlessly copying random code from random places.
|
||||
- Keep the code's *license* in mind. Some licenses allow you to copy code freely, some require you to give credit and some don't allow you to copy any code at all. Even if a project allows you to copy code without giving credit, it's always good practice to do so anyway.
|
||||
|
||||
# How much work did it take to make Actually Additions
|
||||
> ...from start to finish? Also how long did it take you to go from an idea to a first "prototype"? (Spo0ok)
|
||||
|
||||
This is an incredibly tough question, because of course I didn't record an exact measurement of how many hours I sunk into creating Actually Additions. What I do know, however, is this: It look *a long time*. Actually Additions was one of my first mods, and as previously discussed, I was not very good at any kind of programming when I started out, so I made al ot of mistakes, and I copied a lot of code without understanding it. That being said, I can give a rough estimate based on data that I already discussed in my [post about its features](https://ellpeck.de/blog/actually_additions).
|
||||
|
||||
The first file I uploaded to CurseForge was [this one](https://www.curseforge.com/minecraft/mc-mods/actually-additions/files/2229705), on *March 15, 2015*. I know that, before I started uploading the mod to CurseForge, I had a Minecraft Forum page (it was still that time in 2015), and I would release early versions of the mod on Mediafire or some other site. That wouldn't have lasted that long, though, and looking at the commit history for the mod, the first time I referred to it as Actually Additions wasn't long after the repository was first created, [in March 2015](https://github.com/Ellpeck/ActuallyAdditions/commit/2a2308c0ce35fe8a5ac9dcea100b9aeb941c495a). I made my last real contribution [in June 2017](https://github.com/Ellpeck/ActuallyAdditions/commits/main?after=896a082d747a3e19755ded1973544d59fa992787+244).
|
||||
|
||||
That means, to create all of the features that the mod currently has, it took me about two years. I know that measurement is pretty reasonable, because I took almost no breaks when I first created the mod. This information also means that I have now *not* worked on the mod for longer than I originally *did* work on it. It's been like that for a long while actually, because 2017 is surprisingly far in the past. That's honestly kind of scary. I'm getting old, aren't I?
|
||||
|
||||
---
|
||||
|
||||
So yea, that's about it in terms of modding-related questions. I hope you found this post enjoyable. If you did, and if you have more questions for me to answer, you can always reply to the discussion tweet linked right at the end of this post, and if there are enough additional questions, I might make a second one.
|
||||
|
||||
Anyway, thanks for reading! ❤
|
||||
|
||||
---
|
||||
|
||||
[^1]: Method chaining is a concept that is used in a few languages, but especially Java. The idea is that, when you create non-static methods that change certain properties about an object, you make the method return *the object itself*. This allows for multiple method calls to be done in one line, which is especially useful when creating a system where you apply a bunch of settings to an object. `new Block().setHardness(3).setLightLevel(15);`
|
||||
|
||||
[^2]: Short-circuiting out of methods using `return` instead of having a bunch of nested checks
|
|
@ -1,142 +1,142 @@
|
|||
---
|
||||
layout: blog
|
||||
title: ❤️ Em & Ben
|
||||
summary: Ben hates public gatherings because he suffers from anxiety. He's also in love with his best friend Emily, who frequently tries to drag him out of his shell. At the spring festival, he has a panic attack. Will Emily manage to support him?
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
reedsy: https://blog.reedsy.com/creative-writing-prompts/contests/86/submissions/59997/
|
||||
discuss: https://twitter.com/Ellpeck/status/1374770369169653767
|
||||
---
|
||||
|
||||
# Chapter 1
|
||||
There'd never been a day quite like Tuesday, February 17. It was a warm, spring day, and the newly awakened sun was warming Ben's freckle-ridden face. He didn't know it just yet, but this would be the day that Ben would almost die. Well, that's the way he'd think of it *afterwards*, anyway.
|
||||
|
||||
The park was unusually packed with people, and for a second, Ben debated whether turning back was a good idea after all. He'd had these thoughts a lot recently; wanting to just turn back and run away from things. He ran a hand through his long, silky hair and turned around. *Damn it*, he thought, before he snapped back to facing the center of the park. *I have to do this.*
|
||||
|
||||
From afar, he could just about make out what was going on around the large fountain. The water was splashing out of what he'd always just assumed to be a large fish, though he didn't have the ability to tell for sure, because the fountain was old and rugged and had probably been just-about-fixed one too many times before. Ben squinted a bit before raising his glasses in an attempt to make out the faces of the people he saw, sitting and standing around the fountain, talking. He was looking for his best friend, Emily. She was really the kind of person that would drag him to outings like this; public gatherings and any sort of parties were terrifying to Ben. It was natural then that he would find a best friend that is his absolute polar opposite: Popular, blonde and, of course, an absolute party animal. *Damn it, Em, where are you?*, he mumbled to no one in particular.
|
||||
|
||||
He started approaching the fountain and the square around it. Several small crowds of people were standing around little stalls that emitted vastly different smells. Amidst all of this mess, he was almost certain he could smell bubblegum ice cream. Hectically looking around in an attempt to find his friend, he tried to suppress any memory related to bubble gum. To ice cream. To the life that he'd had before he changed. *Fuck*, he quietly said to himself.
|
||||
|
||||
The smell of the bubblegum ice cream started getting too strong for him to handle, and memories started welling up inside of him. His brain was unfolding like a book, too heavy to close. Ben pictured a red, rickety swing set in the middle of a park much like the one he was in right now. He pictured Emily, and for a moment, he pictured the way it had felt. The way the wind blew through his hair as he threw his legs back and forth on the swings, laughing with Em about wanting to do a three hundred and sixty degree turn. Had he already called her *Em* back then?
|
||||
|
||||
He immediately snapped back into reality when he felt the tap of something on his shoulder. Immediately might have been generous, because the tap really did feel like a heavy knock. Maybe it had taken him a few seconds to come back. His eyes felt a bit watery and his knees were shaking, but he told himself that he was probably just hungry (he wasn't) and turned around to discover the source of the heavy tapping.
|
||||
|
||||
"Ben!", Emily exclaimed right behind him. She was a beautiful woman with curly hair and a smile that probably tasted like bubblegum ice cream. *Tasted?*
|
||||
|
||||
"Hey, Emily, why'd you take so long?", he asked in the flattest possible tone.
|
||||
|
||||
"Shut up", she returned with a snarky grin. *Damn*, she looked extra beautiful today. Ben looked down at her flowy, blue skirt and matching light purple ballerinas. Even though his eyes were still watery, he couldn't help but smile at the look of her, standing there right in front of him. This is exactly what she did to him.
|
||||
|
||||
"Oh man, I want some fro-yo right about now!", Emily sighed yearningly as she grasped Ben's upper arm and started pulling him towards one of the stalls by the fountain. "You want some too? I can pay."
|
||||
|
||||
"Are you kidding me? You're *broke*, I'm not letting you pay for *anything*!"
|
||||
|
||||
"*Broke*? Come on, that's a bit harsh", she countered and frowned. She stopped dead in her tracks, let go of his upper arm and, after a few seconds of fondling with her cardigan, produced a thirty-dollar bill out of what he could only assume to be a hidden pocket somewhere. "See?"
|
||||
|
||||
Not entirely convinced of Emily's sudden wealth, he raised an eyebrow and tilted his head slightly in disapproval. "Fine."
|
||||
|
||||
# Chapter 2
|
||||
Over the next few hours, Ben was dragged back and forth between stalls and attractions. For every single one, he was apprehensive at first but rather quickly changed his mind once Emily frowned. It was such a heart-melting frown, worse than the faces that his aunt's dogs would make when they wanted to be taken for a long walk. Every single thing about Emily was just so beautiful that he could be happy doing anything with her. Even going to a shoddy, uncomfortable carnival in the middle of February.
|
||||
|
||||
They'd already stopped at almost every ride and stall, and so Ben decided that now was enough. He wasn't usually the type of person to make decisions like this (he'd just leave it up to whoever else was actually in charge), but this time, he'd put his foot down. He would, absolutely.
|
||||
|
||||
"Em, I'm getting tired."
|
||||
|
||||
"Are you serious? We haven't even eaten any churros yet!" Emily smiled devilishly at him while tugging on his blue sweatshirt's right sleeve. She was staring at him, as if trying to extract the information directly from his eyes. Her blonde locks were flowing over her brow and almost into her eyes, but that didn't seem to bother her. He guessed that, after a while, you'd probably get used to it, like you do with seeing your own nose. He really liked seeing her nose, though.
|
||||
|
||||
"You *love* churros," she pointed out with an overly exaggerated *o* in *love*.
|
||||
|
||||
*In love*, he thought. This time, he was going to put his foot down, right? That's what he'd decided. He didn't want people to control him anymore. But was that really what Emily was doing here? No. She was his best friend, she knew what was good for him. Right? She was looking at him, in obvious anticipation of his answer. He did really like churros. But did he love them? He wasn't sure about that. Okay, he did love them, but did he love them enough to warrant another thirty minutes at this godforsaken carnival?
|
||||
|
||||
He loved Emily, that was for certain.
|
||||
|
||||
Wait, what? Had he really just thought that? No, he couldn't have. That was just one of those jokes his brain made up sometimes. Amusing, albeit slightly infuriating. *Fuck off*, he said to himself.
|
||||
|
||||
"What?", Emily replied, clearly confused as to what he was saying. He wasn't saying anything though, right? What had he said?
|
||||
|
||||
"I'm, the," he mumbled, trying to make sense of what Emily could've just heard him say. Maybe she didn't hear anything, maybe it was just the wind. What could he have said to her? Surely he didn't say the love part out loud, right?
|
||||
|
||||
He stared at her face. Her brown eyes were intensely focusing on him, her lips slightly curled into a smile. She tugged on his sweatshirt one last time.
|
||||
|
||||
"So, churros?" Oh Thank God.
|
||||
|
||||
"*Fine.*"
|
||||
|
||||
***
|
||||
|
||||
As they were eating their churros, Ben couldn't help but notice how much chocolate sauce Emily had on hers with every bite. They'd ordered a little square box filled with twelve or so standing churros, along with a small tub of chocolate sauce that tasted criminally close to Nutella without actually being Nutella.
|
||||
|
||||
"You know this sauce is for dipping, right?", he said to her with a grin before taking another huge bite. "It's not supposed to be a full-on coating."
|
||||
|
||||
"What do you know, huh? Where does it say that?" She tutted and shoved her churro into the tub of sauce with ostentation. While pulling out the excessively coated pastry, she got ready to put her other hand under it as to prevent any of the chocolate sauce from dripping down onto her dress.
|
||||
"Try it!", she said with an impish smile and held the dripping mess right up to Ben's mouth.
|
||||
|
||||
"No, I don't—" He tried to interject, but Emily had already rammed the chocolate-covered churro directly into his face. He resisted opening his mouth, so the chocolate sauce smeared all over this face and chin and then continued to drip onto his sweatshirt in big, brown globs. "Damn it, Em."
|
||||
|
||||
"I'm sorry, but why didn't you open your mouth?", she asked jokingly while holding back laughter.
|
||||
|
||||
"Fuck," he said angrily and fumbled around his pockets, trying to find a tissue or something. In the scramble, the smells of the chocolate on his face and the odor of bubblegum ice cream in the air mixed to create something awfully unpleasant in his nose. He was trying really hard to find a tissue now.
|
||||
|
||||
"Damn it, Em, why do you always have to do that?"
|
||||
|
||||
"Oh, *come on*, that isn't fair! I was just trying to have fun!"
|
||||
|
||||
"Fun? You know I hate these kinds of things. I hate *people*!"
|
||||
|
||||
She tutted. "Lighten up a bit, Ben!"
|
||||
|
||||
"Lighten the *fuck* up?" His brain was unfolding again, this time like floodgates, unable to be stopped by the water pushing against them. "You don't understand me at all!"
|
||||
|
||||
He was yelling now, and some people around them were beginning to notice. Fuck. He finally looked over at Emily, his face still covered in chocolate sauce, but she wasn't smiling anymore. Instead, she had this look on her face that she'd sometimes get. When watching a sad documentary, or when her mom prepared food that she didn't particularly enjoy. It wasn't a frown, it was more of a neutral expression of… disapproval? Disgust?
|
||||
|
||||
"Why is everything such a big fucking deal to you, Ben?", she yelled, tears starting to escape from her half-shut, pained eyes.
|
||||
|
||||
That was the moment a switch in his brain finally flicked. A switch that was probably in a back room, guarded by multiple doors with multiple, separate keys. Use only in emergencies, a sign somewhere close to the switch probably said. Don't use even, maybe. Ben tried to force his eyes shut with extreme determination. No, he wouldn't cry.
|
||||
|
||||
But he did. Tears started running down his face like waterfalls, and he tried to cover them up and wipe them away with the sleeve of his sweatshirt. He wiped his cheeks with the sleeves of his blue sweatshirt, and large amounts of chocolate sauce transferred from his face to the sleeves. God fucking damn it, he muttered to himself. The world around him was turning into a very small part of his vision, the rest filled with blurry streams of tears. He tried to get up from the bench they were sitting on and stumbled around the square where the festival was happening. He was sure he'd bumped into a few people on the way, but couldn't tell for absolute certain. After what felt like an hour and a half, he finally arrived at a tree a few meters away from the fountain square.
|
||||
|
||||
He rested one hand against the bark and tried to catch his breath. The thought of bubblegum ice cream was fresh in his mind again, the thought of the red, rickety swing set was morphing and mixing with the thought of churros, the thought of chocolate sauce in his face. The thought of Emily's smile, the thought of her frown, the thought of her sad movie face. Fuck.
|
||||
|
||||
He tried telling himself to breathe. *Five in, six hold, seven out.* That's what his therapist had told him. *One, two, three.* What's the worst that could realistically happen?, that's what he was supposed to ask himself. *Four, five.* Well. *One, two, three.* Emily might never talk to him again. *Four, five, six.* She might hate him, now that she'd just tried to be cute by shoving a churro into his face, and now that he'd reacted like a total fucking asshole. *One, two.* Was he already breathing in again? *Fuck.* He kept telling his body to calm down, his mind to stop racing. His heart to stop racing. He started leaning against the bark and then slowly slid down the tree trunk, sitting down on the ground with his knees close to his chest. He observed the rickety swing set in the middle of the field, and saw himself and Emily swinging back and forth again, talking about three hundred and sixty degree swings. He saw himself, laughing and giggling and occasionally licking a cone of bubble gum soft serve he had in his left hand. He saw Emily doing the same. He saw himself wobbling a bit on the swing, trying to hold himself steady with just his right hand. He tried to breathe again. *One, two, three.* He saw himself, still holding the cone, sliding out of the swing's seat and yelling something. He saw himself landing in the rough, wet sand, the cone having left his hand and landing face-down in the sand next to him. *Four, five.* Tears were still running down his face. He saw himself turning around as Emily jumped off of her swing and came to his rescue.
|
||||
|
||||
"Are you alright?", he heard her say in her beautiful, melodic voice. *One, two, three.*
|
||||
|
||||
"I would've been, if you hadn't forced me to get this stupid ice cream!", he heard himself shoot back aggressively.
|
||||
|
||||
He felt something tap on his shoulder again.
|
||||
|
||||
"Are you alright?", he heard someone say. "I'm sorry, I shouldn't have said that."
|
||||
|
||||
It was Emily, standing next to him, bending down a bit to reach his shoulders. She slid down the tree trunk next to him. "I'm really sorry."
|
||||
|
||||
Ben tried to catch his breath, but with Emily here, it felt much easier all of a sudden. It's like a tension had been lifted from him, like someone had come to push on the floodgates from the other side. "It's alright. I'm sorry I yelled, too."
|
||||
|
||||
Emily tutted.
|
||||
|
||||
"You know, sometimes I think of that day on the swings."
|
||||
|
||||
"What day?"
|
||||
|
||||
"The day we had our first fight. Don't you remember?"
|
||||
|
||||
Emily tutted again. She placed her hand back on his shoulder, which he liked, because it was Emily's hand. That's all that mattered to him.
|
||||
|
||||
He wiped the remaining tears and chocolate sauce off of his face, his sweatshirt's sleeves now completely covered in both. "I keep remembering that day, being scared that I'll re-live it. That we'll have another fight. That you'll leave."
|
||||
|
||||
"*Leave*? Come on."
|
||||
|
||||
"I'm serious."
|
||||
|
||||
"I am, too. I'm not leaving."
|
||||
|
||||
She scooched closer and rested her head on his shoulder. "You know, I think about stuff too."
|
||||
|
||||
"Like what?", he asked while also resting his head on her head, which made him feel really close to her. Intertwined, even.
|
||||
|
||||
"You", she said quietly and grunted. "I really like hanging out with you, you know?"
|
||||
|
||||
"I do too," he said almost immediately. Did this mean what he thought it meant?
|
||||
|
||||
"Do you want to go home? I'm sure my mom has cookies."
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: ❤️ Em & Ben
|
||||
description: Ben hates public gatherings because he suffers from anxiety. He's also in love with his best friend Emily, who frequently tries to drag him out of his shell. At the spring festival, he has a panic attack. Will Emily manage to support him?
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
reedsy: https://blog.reedsy.com/creative-writing-prompts/contests/86/submissions/59997/
|
||||
discuss: https://twitter.com/Ellpeck/status/1374770369169653767
|
||||
---
|
||||
|
||||
# Chapter 1
|
||||
There'd never been a day quite like Tuesday, February 17. It was a warm, spring day, and the newly awakened sun was warming Ben's freckle-ridden face. He didn't know it just yet, but this would be the day that Ben would almost die. Well, that's the way he'd think of it *afterwards*, anyway.
|
||||
|
||||
The park was unusually packed with people, and for a second, Ben debated whether turning back was a good idea after all. He'd had these thoughts a lot recently; wanting to just turn back and run away from things. He ran a hand through his long, silky hair and turned around. *Damn it*, he thought, before he snapped back to facing the center of the park. *I have to do this.*
|
||||
|
||||
From afar, he could just about make out what was going on around the large fountain. The water was splashing out of what he'd always just assumed to be a large fish, though he didn't have the ability to tell for sure, because the fountain was old and rugged and had probably been just-about-fixed one too many times before. Ben squinted a bit before raising his glasses in an attempt to make out the faces of the people he saw, sitting and standing around the fountain, talking. He was looking for his best friend, Emily. She was really the kind of person that would drag him to outings like this; public gatherings and any sort of parties were terrifying to Ben. It was natural then that he would find a best friend that is his absolute polar opposite: Popular, blonde and, of course, an absolute party animal. *Damn it, Em, where are you?*, he mumbled to no one in particular.
|
||||
|
||||
He started approaching the fountain and the square around it. Several small crowds of people were standing around little stalls that emitted vastly different smells. Amidst all of this mess, he was almost certain he could smell bubblegum ice cream. Hectically looking around in an attempt to find his friend, he tried to suppress any memory related to bubble gum. To ice cream. To the life that he'd had before he changed. *Fuck*, he quietly said to himself.
|
||||
|
||||
The smell of the bubblegum ice cream started getting too strong for him to handle, and memories started welling up inside of him. His brain was unfolding like a book, too heavy to close. Ben pictured a red, rickety swing set in the middle of a park much like the one he was in right now. He pictured Emily, and for a moment, he pictured the way it had felt. The way the wind blew through his hair as he threw his legs back and forth on the swings, laughing with Em about wanting to do a three hundred and sixty degree turn. Had he already called her *Em* back then?
|
||||
|
||||
He immediately snapped back into reality when he felt the tap of something on his shoulder. Immediately might have been generous, because the tap really did feel like a heavy knock. Maybe it had taken him a few seconds to come back. His eyes felt a bit watery and his knees were shaking, but he told himself that he was probably just hungry (he wasn't) and turned around to discover the source of the heavy tapping.
|
||||
|
||||
"Ben!", Emily exclaimed right behind him. She was a beautiful woman with curly hair and a smile that probably tasted like bubblegum ice cream. *Tasted?*
|
||||
|
||||
"Hey, Emily, why'd you take so long?", he asked in the flattest possible tone.
|
||||
|
||||
"Shut up", she returned with a snarky grin. *Damn*, she looked extra beautiful today. Ben looked down at her flowy, blue skirt and matching light purple ballerinas. Even though his eyes were still watery, he couldn't help but smile at the look of her, standing there right in front of him. This is exactly what she did to him.
|
||||
|
||||
"Oh man, I want some fro-yo right about now!", Emily sighed yearningly as she grasped Ben's upper arm and started pulling him towards one of the stalls by the fountain. "You want some too? I can pay."
|
||||
|
||||
"Are you kidding me? You're *broke*, I'm not letting you pay for *anything*!"
|
||||
|
||||
"*Broke*? Come on, that's a bit harsh", she countered and frowned. She stopped dead in her tracks, let go of his upper arm and, after a few seconds of fondling with her cardigan, produced a thirty-dollar bill out of what he could only assume to be a hidden pocket somewhere. "See?"
|
||||
|
||||
Not entirely convinced of Emily's sudden wealth, he raised an eyebrow and tilted his head slightly in disapproval. "Fine."
|
||||
|
||||
# Chapter 2
|
||||
Over the next few hours, Ben was dragged back and forth between stalls and attractions. For every single one, he was apprehensive at first but rather quickly changed his mind once Emily frowned. It was such a heart-melting frown, worse than the faces that his aunt's dogs would make when they wanted to be taken for a long walk. Every single thing about Emily was just so beautiful that he could be happy doing anything with her. Even going to a shoddy, uncomfortable carnival in the middle of February.
|
||||
|
||||
They'd already stopped at almost every ride and stall, and so Ben decided that now was enough. He wasn't usually the type of person to make decisions like this (he'd just leave it up to whoever else was actually in charge), but this time, he'd put his foot down. He would, absolutely.
|
||||
|
||||
"Em, I'm getting tired."
|
||||
|
||||
"Are you serious? We haven't even eaten any churros yet!" Emily smiled devilishly at him while tugging on his blue sweatshirt's right sleeve. She was staring at him, as if trying to extract the information directly from his eyes. Her blonde locks were flowing over her brow and almost into her eyes, but that didn't seem to bother her. He guessed that, after a while, you'd probably get used to it, like you do with seeing your own nose. He really liked seeing her nose, though.
|
||||
|
||||
"You *love* churros," she pointed out with an overly exaggerated *o* in *love*.
|
||||
|
||||
*In love*, he thought. This time, he was going to put his foot down, right? That's what he'd decided. He didn't want people to control him anymore. But was that really what Emily was doing here? No. She was his best friend, she knew what was good for him. Right? She was looking at him, in obvious anticipation of his answer. He did really like churros. But did he love them? He wasn't sure about that. Okay, he did love them, but did he love them enough to warrant another thirty minutes at this godforsaken carnival?
|
||||
|
||||
He loved Emily, that was for certain.
|
||||
|
||||
Wait, what? Had he really just thought that? No, he couldn't have. That was just one of those jokes his brain made up sometimes. Amusing, albeit slightly infuriating. *Fuck off*, he said to himself.
|
||||
|
||||
"What?", Emily replied, clearly confused as to what he was saying. He wasn't saying anything though, right? What had he said?
|
||||
|
||||
"I'm, the," he mumbled, trying to make sense of what Emily could've just heard him say. Maybe she didn't hear anything, maybe it was just the wind. What could he have said to her? Surely he didn't say the love part out loud, right?
|
||||
|
||||
He stared at her face. Her brown eyes were intensely focusing on him, her lips slightly curled into a smile. She tugged on his sweatshirt one last time.
|
||||
|
||||
"So, churros?" Oh Thank God.
|
||||
|
||||
"*Fine.*"
|
||||
|
||||
***
|
||||
|
||||
As they were eating their churros, Ben couldn't help but notice how much chocolate sauce Emily had on hers with every bite. They'd ordered a little square box filled with twelve or so standing churros, along with a small tub of chocolate sauce that tasted criminally close to Nutella without actually being Nutella.
|
||||
|
||||
"You know this sauce is for dipping, right?", he said to her with a grin before taking another huge bite. "It's not supposed to be a full-on coating."
|
||||
|
||||
"What do you know, huh? Where does it say that?" She tutted and shoved her churro into the tub of sauce with ostentation. While pulling out the excessively coated pastry, she got ready to put her other hand under it as to prevent any of the chocolate sauce from dripping down onto her dress.
|
||||
"Try it!", she said with an impish smile and held the dripping mess right up to Ben's mouth.
|
||||
|
||||
"No, I don't—" He tried to interject, but Emily had already rammed the chocolate-covered churro directly into his face. He resisted opening his mouth, so the chocolate sauce smeared all over this face and chin and then continued to drip onto his sweatshirt in big, brown globs. "Damn it, Em."
|
||||
|
||||
"I'm sorry, but why didn't you open your mouth?", she asked jokingly while holding back laughter.
|
||||
|
||||
"Fuck," he said angrily and fumbled around his pockets, trying to find a tissue or something. In the scramble, the smells of the chocolate on his face and the odor of bubblegum ice cream in the air mixed to create something awfully unpleasant in his nose. He was trying really hard to find a tissue now.
|
||||
|
||||
"Damn it, Em, why do you always have to do that?"
|
||||
|
||||
"Oh, *come on*, that isn't fair! I was just trying to have fun!"
|
||||
|
||||
"Fun? You know I hate these kinds of things. I hate *people*!"
|
||||
|
||||
She tutted. "Lighten up a bit, Ben!"
|
||||
|
||||
"Lighten the *fuck* up?" His brain was unfolding again, this time like floodgates, unable to be stopped by the water pushing against them. "You don't understand me at all!"
|
||||
|
||||
He was yelling now, and some people around them were beginning to notice. Fuck. He finally looked over at Emily, his face still covered in chocolate sauce, but she wasn't smiling anymore. Instead, she had this look on her face that she'd sometimes get. When watching a sad documentary, or when her mom prepared food that she didn't particularly enjoy. It wasn't a frown, it was more of a neutral expression of… disapproval? Disgust?
|
||||
|
||||
"Why is everything such a big fucking deal to you, Ben?", she yelled, tears starting to escape from her half-shut, pained eyes.
|
||||
|
||||
That was the moment a switch in his brain finally flicked. A switch that was probably in a back room, guarded by multiple doors with multiple, separate keys. Use only in emergencies, a sign somewhere close to the switch probably said. Don't use even, maybe. Ben tried to force his eyes shut with extreme determination. No, he wouldn't cry.
|
||||
|
||||
But he did. Tears started running down his face like waterfalls, and he tried to cover them up and wipe them away with the sleeve of his sweatshirt. He wiped his cheeks with the sleeves of his blue sweatshirt, and large amounts of chocolate sauce transferred from his face to the sleeves. God fucking damn it, he muttered to himself. The world around him was turning into a very small part of his vision, the rest filled with blurry streams of tears. He tried to get up from the bench they were sitting on and stumbled around the square where the festival was happening. He was sure he'd bumped into a few people on the way, but couldn't tell for absolute certain. After what felt like an hour and a half, he finally arrived at a tree a few meters away from the fountain square.
|
||||
|
||||
He rested one hand against the bark and tried to catch his breath. The thought of bubblegum ice cream was fresh in his mind again, the thought of the red, rickety swing set was morphing and mixing with the thought of churros, the thought of chocolate sauce in his face. The thought of Emily's smile, the thought of her frown, the thought of her sad movie face. Fuck.
|
||||
|
||||
He tried telling himself to breathe. *Five in, six hold, seven out.* That's what his therapist had told him. *One, two, three.* What's the worst that could realistically happen?, that's what he was supposed to ask himself. *Four, five.* Well. *One, two, three.* Emily might never talk to him again. *Four, five, six.* She might hate him, now that she'd just tried to be cute by shoving a churro into his face, and now that he'd reacted like a total fucking asshole. *One, two.* Was he already breathing in again? *Fuck.* He kept telling his body to calm down, his mind to stop racing. His heart to stop racing. He started leaning against the bark and then slowly slid down the tree trunk, sitting down on the ground with his knees close to his chest. He observed the rickety swing set in the middle of the field, and saw himself and Emily swinging back and forth again, talking about three hundred and sixty degree swings. He saw himself, laughing and giggling and occasionally licking a cone of bubble gum soft serve he had in his left hand. He saw Emily doing the same. He saw himself wobbling a bit on the swing, trying to hold himself steady with just his right hand. He tried to breathe again. *One, two, three.* He saw himself, still holding the cone, sliding out of the swing's seat and yelling something. He saw himself landing in the rough, wet sand, the cone having left his hand and landing face-down in the sand next to him. *Four, five.* Tears were still running down his face. He saw himself turning around as Emily jumped off of her swing and came to his rescue.
|
||||
|
||||
"Are you alright?", he heard her say in her beautiful, melodic voice. *One, two, three.*
|
||||
|
||||
"I would've been, if you hadn't forced me to get this stupid ice cream!", he heard himself shoot back aggressively.
|
||||
|
||||
He felt something tap on his shoulder again.
|
||||
|
||||
"Are you alright?", he heard someone say. "I'm sorry, I shouldn't have said that."
|
||||
|
||||
It was Emily, standing next to him, bending down a bit to reach his shoulders. She slid down the tree trunk next to him. "I'm really sorry."
|
||||
|
||||
Ben tried to catch his breath, but with Emily here, it felt much easier all of a sudden. It's like a tension had been lifted from him, like someone had come to push on the floodgates from the other side. "It's alright. I'm sorry I yelled, too."
|
||||
|
||||
Emily tutted.
|
||||
|
||||
"You know, sometimes I think of that day on the swings."
|
||||
|
||||
"What day?"
|
||||
|
||||
"The day we had our first fight. Don't you remember?"
|
||||
|
||||
Emily tutted again. She placed her hand back on his shoulder, which he liked, because it was Emily's hand. That's all that mattered to him.
|
||||
|
||||
He wiped the remaining tears and chocolate sauce off of his face, his sweatshirt's sleeves now completely covered in both. "I keep remembering that day, being scared that I'll re-live it. That we'll have another fight. That you'll leave."
|
||||
|
||||
"*Leave*? Come on."
|
||||
|
||||
"I'm serious."
|
||||
|
||||
"I am, too. I'm not leaving."
|
||||
|
||||
She scooched closer and rested her head on his shoulder. "You know, I think about stuff too."
|
||||
|
||||
"Like what?", he asked while also resting his head on her head, which made him feel really close to her. Intertwined, even.
|
||||
|
||||
"You", she said quietly and grunted. "I really like hanging out with you, you know?"
|
||||
|
||||
"I do too," he said almost immediately. Did this mean what he thought it meant?
|
||||
|
||||
"Do you want to go home? I'm sure my mom has cookies."
|
||||
|
||||
He nodded. Maybe it did.
|
|
@ -1,148 +1,148 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 👫 Emily's Fake Boyfriend
|
||||
summary: Emily's aunt keeps going on about her love life. To solve this problem, she pretends to be in a relationship with her best friend, Ben, who'd much rather have a real relationship with her. How will an evening with the three of them at the same table play out?
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
discuss: https://twitter.com/Ellpeck/status/1378014977999659016
|
||||
---
|
||||
|
||||
# Chapter 1
|
||||
For Emily, Saturdays always seemed to be the days when most things went wrong. She didn't exactly know why, but she was almost certain that there was some pattern, some sort of spiteful spirit that hated Saturdays, hated her, or both. This Saturday would be one of the most bizarre ones so far, but she didn't know that yet.
|
||||
|
||||
The alarm rang, its screeching noises filling Emily's bedroom. With a huge sigh, she pulled the cover off of her body and jumped out of bed. As she picked up her phone from the nightstand, she sighed again. *Oh God*, she thought. *What now?* She tapped various locations of the device's large screen until she ended up in a text message chain with her mom, her brother and her younger sister. Her eyes kept trying to entice her to fall back asleep while she was scanning the lines of the last ten or so messages as carefully as she could.
|
||||
|
||||
*Damn it*, she thought as she got to the last message. *That's today*? She quickly gathered her things, put on her favorite, pastel pink cardigan, messily fluffed up her hair as she ran past her large mirror and made her way downstairs.
|
||||
|
||||
"Good morning!" Her mom said with a slight smile. She was standing in the kitchen, as she usually did, preparing homemade waffles. Emily's mother was a very good cook and baker, but waffles weren't her strong suit, for some reason. Every time she tried (and she tried too much), they'd end up burnt or somehow taste of licorice. The thought made Emily grimace as she walked past the kitchen.
|
||||
|
||||
"Morning, mom!" she hastily said and made her way to the front door.
|
||||
|
||||
"Not so fast," her mom shouted back from the kitchen. "Don't forget your waffles!"
|
||||
|
||||
*Oh, God.* "Of course," Emily replied with a sigh.
|
||||
|
||||
***
|
||||
|
||||
Ben was sitting on the side of his bed with his laptop firmly planted on his crossed legs. With the speed of a twenty-fingered person, he was typing away on an essay for school. He heard a knock on his room door and, while *very* annoyed by this, he still managed to calmly shout "Come in!"
|
||||
|
||||
"Emily's here," his mom said while peeking her head through the slightly opened door. "She says it's important."
|
||||
|
||||
Almost immediately, far too many thoughts started sprinting through his head: It's *important*? What could that possibly mean? Was Em, his best friend since kindergarten, *dying*? No, that's unlikely. But what if she *was*? Why wouldn't she just *call*? Oh God, no, a call would be *even worse*. Still begging his brain to shut up, he trotted down the stairs and arrived in the house's main hallway. A myriad of family photos plastered the walls, most of them from when Ben was still a child. His mom *loved* showing off pictures of his "little baby boy," evidently in the most embarrassing ways possible.
|
||||
|
||||
"Ben!" Emily said hastily as he opened the door. "I need you to be my boyfriend!"
|
||||
|
||||
*His what*? His mind began racing again. Not only was that a very weird way to phrase that sort of thing, but it was also an extremely unexpected request in general. Emily, while insanely beautiful and extremely charming, wasn't really known to start relationships with anyone. Ben occasionally talked to her about it. It didn't seem to be her favorite topic, so usually, he'd lay off after only two or three questions. They weren't necessarily the easiest of questions for him to ask her, either, because he was *obsessed* with her, almost uncomfortably so. Not in a stalker-y, watch-her-every-night, masturbate-to-her-daily sort of way, but in an I-love-you-and-I-want-to-marry-you kind of way. Of course, Ben (being who he is) was far too self-conscious to *ever* bring it up.
|
||||
|
||||
"You need to *what*?", he responded quickly.
|
||||
|
||||
"Well," she said and took a deep breath. "My aunt is coming to town and I may or may not have told her that we're, uh, together."
|
||||
|
||||
"You did *what*?"
|
||||
|
||||
"I know, I know. It's bad." She tutted. "The thing is that my aunt can be really *annoying*. She always goes on and on about my love life, about how I haven't found a boyfriend yet, even though I'm already 19, and how that is *absolutely unacceptable*. So, I decided to put a stop to it."
|
||||
|
||||
Ben closed his eyes. *Fuck.* Of course, it wasn't what he'd hoped it was. *Of course*, she didn't want to be his *actual* girlfriend. Who'd want to be? Nobody. Especially not her.
|
||||
|
||||
She was standing there, her blonde locks swaying back and forth in the breeze that the open front door let in, and Ben was lost for words.
|
||||
|
||||
She tutted again. "Aren't you going to say anything?"
|
||||
|
||||
"Well," he started. How could he say yes to this? If anything, wouldn't it just cause him more pain to have an entirely fake relationship than none at all? Maybe. But maybe, this could lead to something. Maybe, he thought, this could be like those cheesy romance films that he sometimes watched when he was in a *particular* mood. Maybe this could really be the start of something.
|
||||
|
||||
"What do you need me to do?" He asked.
|
||||
|
||||
***
|
||||
|
||||
Emily breathed a huge sigh of relief. "Let's sit down somewhere," she said quietly.
|
||||
|
||||
As she finally entered the house, and they started making their way over to Ben's living room, she felt a kind of unease course through her body. It wasn't the *bad Saturday waffles* kind. She couldn't quite put her finger on what this feeling was, but she felt her heart beating faster when they sat down on a rickety, brown sofa.
|
||||
|
||||
She knew, of course, that Ben didn't enjoy this whole situation. She knew that he wasn't the best liar, and she knew that he didn't *enjoy* lying all that much either. But this was different, she thought to herself. Emily never understood what, if anything, Ben felt for her. It wasn't that he was secretive about his feelings, it's that she was incredibly bad at reading them. To her, it was weird that so many people automatically *assumed* that she was amazing at talking to people, making conversation, and understanding what other people want. But this wasn't really the case. While Emily *did* love hanging out with people, the part of her brain that was meant for understanding people's feelings was probably being repurposed to store excessive amounts of Ariana Grande quotes. And it made her feel bad, too, because her best friend Ben was absolutely *packed* with feelings.
|
||||
|
||||
While poking at a small hole in the brown fabric she was sitting on, she recalled a situation from a few months ago. She and Ben were in the park, and there was some sort of spring festival going on. She had dragged him out to it because, even though she didn't necessarily *like* taking this role in his life, she'd often try to take him out of his shell and help him fight his anxiety. During that festival, he had a full-on *panic attack* (the kind of thing that she, as an avid Ariana Grande listener, did not understand), which caused him to run off and hide.
|
||||
|
||||
Was this really such a good idea?
|
||||
|
||||
"Okay, so," she said and let out a big sigh. "Let's talk relationship. What kind of boyfriend do you want to be?"
|
||||
|
||||
"I'm sorry?" He said, flustered.
|
||||
|
||||
"Well, I didn't tell my aunt that many lies about you, so the whole thing is pretty open. You can be super caring, or, you know, the bad boy type."
|
||||
|
||||
"The *bad boy type*?"
|
||||
|
||||
"Yea, like, uncaring and aloof, you know? Maybe wear a leather jacket."
|
||||
|
||||
"A leather- have you *met me*?" He responded in playful disgust.
|
||||
|
||||
"Okay, super caring it is, then," she laughed and moved her hands around in the air as if writing something down on a giant, invisible notebook.
|
||||
|
||||
Honestly, *super caring* was exactly the kind of boyfriend that she actually wanted. Of course, she would never say this out loud, but occasionally she dreamed of the perfect storybook romance. *Romeo and Juliet*, just without all the tragic stuff. Just like that one Taylor Swift song. While she'd fooled around with some of her girlfriends once or twice, she'd never actually had a relationship with anyone, especially not a guy. She didn't really know why, either. She briefly wondered if any guys had ever been visibly into her. Maybe she'd just missed it.
|
||||
|
||||
She'd also never admit *this*, of course, but Ben seemed like a fairly good candidate for the position of the super caring boyfriend. He was innocent, sweet, and he had the mane of an extremely gentle lion.
|
||||
|
||||
Uncomfortable silence had set in between the two, as it sometimes seemed to do. It didn't help that Emily had one of those weird thoughts again. Very occasionally, she'd have this intrusive image in her head: Ben, lion-like as he looked, not-so-gently on top of her. Sometimes he'd touch her breasts; sometimes they'd be kissing. Was she sexualizing her friendship? Maybe. Was that bad? She didn't know. She also didn't know if she cared yet. After all, she didn't *mean to*. It just kind of happened every now and again. If anything, didn't that speak to her fondness of Ben?
|
||||
|
||||
In an attempt to quickly change the subject on her mind, she started telling a story about her aunt.
|
||||
|
||||
"You're going to *love* my aunt," she said sarcastically. He looked at her with a sense of dread in his eyes. "Okay, one time, we were at this restaurant, the whole family all packed into this corner booth, and she would not stop pestering the poor waiter with question after question about the most ridiculous stuff! Every time she waved him back over to our table, he looked more and more tired of her shit."
|
||||
|
||||
"That's actually kind of horrifying," he responded and shook his head slowly.
|
||||
|
||||
"Right?"
|
||||
|
||||
# Chapter 2
|
||||
In the early evening, Ben found himself sitting at a big dinner table, straight across from an overly cheerful looking lady. If he had to guess, Em's aunt was probably around fifty-five years old, maybe a little older. She was slightly hunched over the table, resting one of her arms on it. *That's not how you sit at a table, young man*, he heard his own aunt's voice echoing in his head. Clearly, Emily's aunt didn't care, and from what he'd been told, this wasn't surprising.
|
||||
|
||||
When Emily's mom came into the room from the kitchen, she was carrying a large tray that held a variety of sweet pastries and cookies. Homemade, Ben assumed, waiting to bite into one of those chocolate croissants. Emily's mom set the tray down in the center of the table and pointed at it with an open hand as if to say *There you go, dig in*. So Emily and her sister did. After they finished selecting something they liked, Ben also felt comfortable taking a croissant.
|
||||
|
||||
A chocolate cookie in her delicate fingers, Emily's aunt turned to Emily. "So," she began while raising her thickly overdrawn, black eyebrows. "How have you been, my love?"
|
||||
|
||||
"Well, school's been going pretty well. I've only gotten good grades this semester, and my classes have been bearable."
|
||||
|
||||
Her aunt started smiling wide. "A perfect student as always! I expected nothing less of you, dear."
|
||||
|
||||
Emily provocatively rolled her eyes and sighed. Her aunt didn't seem affected by that at all. Instead, she continued smiling as she bit into her cookie. "And you, love?"
|
||||
|
||||
Confused for a second, Ben realized that she was talking to him now.
|
||||
|
||||
"Me? Oh, well," he stuttered. "School is also going great for me. Emily and I are pretty much on the same level in terms of grades and stuff."
|
||||
|
||||
"On the same level, you say? Maybe that's why you two get along so well! For years now, I've been *absolutely positive* that you two would make the cutest couple. And now it's *finally* happened, God bless."
|
||||
|
||||
Emily sighed, louder this time. Ben let out a stifled chuckle. *I wish*, he thought to himself.
|
||||
|
||||
***
|
||||
|
||||
As the conversation continued over dinner, followed by coffee, Ben felt himself zoning out from time to time. As he continued to observe Em and her aunt conversing, he felt his mind wander to a different world without his control.
|
||||
|
||||
A world where him and Em really *were* a couple. A world where, against all odds, they'd happily been together for years, with their own apartment, with floor-length windows and a balcony. They'd sit outside in the evenings, eating ice cream and sipping on cocktails. They would laugh and share stories of their day while watching the sunset over the park. They'd go into town on the weekends and eat at that little Italian place he keeps wanting to go to. They'd never fight anymore, because they'd be happy. He'd never cry alone, never wonder why he was too *stupid* to tell her how he felt.
|
||||
|
||||
Emily grabbed his hand. "We're going upstairs now," she said and got up from her chair.
|
||||
|
||||
Even though he knew it was fake; even though he knew that her hand in his meant *nothing*, it felt good. He craved contact like this, with someone he really cared about. He'd hug Emily more if it wasn't for his fear of being overbearing. Of being a nuisance. Why did he have to feel that way?
|
||||
|
||||
Emily dragged Ben behind her as she walked up the stairs, her palm still resting in his. When they got to the door of her room, she still hadn't let go of his hand. Why? Was Ben just reading into things again, or did she *enjoy* holding his hand? *Surely not. She'd never enjoy that*, he told himself. Then, as he frequently did, he told himself to stop telling himself things like that.
|
||||
|
||||
Emily finally let go of his hand upon entering her room. This was one of Ben's favorite places to be. Sometimes, he'd imagine him and Em cuddled up together on her bed, sharing a blanket, watching a movie or playing *GTA*.
|
||||
|
||||
He thought about this kind of thing a lot. Of course, he also thought a lot about the fact that he thought about this kind of thing so frequently. Was it bad to have these thoughts? Was he risking ruining his perfect friendship with Emily by making some big romance out of it in his head? Was it unfair to her to keep quiet about it? As they sat down next to each other on the bed, he tried to let these thoughts fade.
|
||||
|
||||
"Thank you *so damn much*, man," Emily said and let out a sigh of relief. "What a nightmare."
|
||||
|
||||
"Oh come on, it wasn't *that* bad."
|
||||
|
||||
"Did you hear what she *said*?" Emily put on a very bad, fake British accent. "I was *absolutely positive*," she mocked. "*My dear.*"
|
||||
|
||||
Ben couldn't help but laugh. "She's not that bad! I thought she was nice."
|
||||
|
||||
"Oh shut up, I *know* you." Did she? "People like her drive you *mad*! You never miss out on an opportunity to hide in your room. You don't *like* her."
|
||||
|
||||
Maybe she did know him. And maybe it was this realization that made him unable to think about the words flying out of his mouth. He let out a quiet, but emotional sigh, and said "I like *you*, though."
|
||||
|
||||
Emily turned and looked into his eyes. As he stared back, he could see a tiny reflection of his face in her brown irises. "I like you too, Ben. You know that," she said.
|
||||
|
||||
Maybe she didn't know him after all. He focused intensely on her face. What if this was the moment to be honest? What if, in the light of this fake relationship, he could finally be true to how he felt? Anxiety boiled up inside him. This was a panic attack just waiting to happen. But he had to try. Right?
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 👫 Emily's Fake Boyfriend
|
||||
description: Emily's aunt keeps going on about her love life. To solve this problem, she pretends to be in a relationship with her best friend, Ben, who'd much rather have a real relationship with her. How will an evening with the three of them at the same table play out?
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
discuss: https://twitter.com/Ellpeck/status/1378014977999659016
|
||||
---
|
||||
|
||||
# Chapter 1
|
||||
For Emily, Saturdays always seemed to be the days when most things went wrong. She didn't exactly know why, but she was almost certain that there was some pattern, some sort of spiteful spirit that hated Saturdays, hated her, or both. This Saturday would be one of the most bizarre ones so far, but she didn't know that yet.
|
||||
|
||||
The alarm rang, its screeching noises filling Emily's bedroom. With a huge sigh, she pulled the cover off of her body and jumped out of bed. As she picked up her phone from the nightstand, she sighed again. *Oh God*, she thought. *What now?* She tapped various locations of the device's large screen until she ended up in a text message chain with her mom, her brother and her younger sister. Her eyes kept trying to entice her to fall back asleep while she was scanning the lines of the last ten or so messages as carefully as she could.
|
||||
|
||||
*Damn it*, she thought as she got to the last message. *That's today*? She quickly gathered her things, put on her favorite, pastel pink cardigan, messily fluffed up her hair as she ran past her large mirror and made her way downstairs.
|
||||
|
||||
"Good morning!" Her mom said with a slight smile. She was standing in the kitchen, as she usually did, preparing homemade waffles. Emily's mother was a very good cook and baker, but waffles weren't her strong suit, for some reason. Every time she tried (and she tried too much), they'd end up burnt or somehow taste of licorice. The thought made Emily grimace as she walked past the kitchen.
|
||||
|
||||
"Morning, mom!" she hastily said and made her way to the front door.
|
||||
|
||||
"Not so fast," her mom shouted back from the kitchen. "Don't forget your waffles!"
|
||||
|
||||
*Oh, God.* "Of course," Emily replied with a sigh.
|
||||
|
||||
***
|
||||
|
||||
Ben was sitting on the side of his bed with his laptop firmly planted on his crossed legs. With the speed of a twenty-fingered person, he was typing away on an essay for school. He heard a knock on his room door and, while *very* annoyed by this, he still managed to calmly shout "Come in!"
|
||||
|
||||
"Emily's here," his mom said while peeking her head through the slightly opened door. "She says it's important."
|
||||
|
||||
Almost immediately, far too many thoughts started sprinting through his head: It's *important*? What could that possibly mean? Was Em, his best friend since kindergarten, *dying*? No, that's unlikely. But what if she *was*? Why wouldn't she just *call*? Oh God, no, a call would be *even worse*. Still begging his brain to shut up, he trotted down the stairs and arrived in the house's main hallway. A myriad of family photos plastered the walls, most of them from when Ben was still a child. His mom *loved* showing off pictures of his "little baby boy," evidently in the most embarrassing ways possible.
|
||||
|
||||
"Ben!" Emily said hastily as he opened the door. "I need you to be my boyfriend!"
|
||||
|
||||
*His what*? His mind began racing again. Not only was that a very weird way to phrase that sort of thing, but it was also an extremely unexpected request in general. Emily, while insanely beautiful and extremely charming, wasn't really known to start relationships with anyone. Ben occasionally talked to her about it. It didn't seem to be her favorite topic, so usually, he'd lay off after only two or three questions. They weren't necessarily the easiest of questions for him to ask her, either, because he was *obsessed* with her, almost uncomfortably so. Not in a stalker-y, watch-her-every-night, masturbate-to-her-daily sort of way, but in an I-love-you-and-I-want-to-marry-you kind of way. Of course, Ben (being who he is) was far too self-conscious to *ever* bring it up.
|
||||
|
||||
"You need to *what*?", he responded quickly.
|
||||
|
||||
"Well," she said and took a deep breath. "My aunt is coming to town and I may or may not have told her that we're, uh, together."
|
||||
|
||||
"You did *what*?"
|
||||
|
||||
"I know, I know. It's bad." She tutted. "The thing is that my aunt can be really *annoying*. She always goes on and on about my love life, about how I haven't found a boyfriend yet, even though I'm already 19, and how that is *absolutely unacceptable*. So, I decided to put a stop to it."
|
||||
|
||||
Ben closed his eyes. *Fuck.* Of course, it wasn't what he'd hoped it was. *Of course*, she didn't want to be his *actual* girlfriend. Who'd want to be? Nobody. Especially not her.
|
||||
|
||||
She was standing there, her blonde locks swaying back and forth in the breeze that the open front door let in, and Ben was lost for words.
|
||||
|
||||
She tutted again. "Aren't you going to say anything?"
|
||||
|
||||
"Well," he started. How could he say yes to this? If anything, wouldn't it just cause him more pain to have an entirely fake relationship than none at all? Maybe. But maybe, this could lead to something. Maybe, he thought, this could be like those cheesy romance films that he sometimes watched when he was in a *particular* mood. Maybe this could really be the start of something.
|
||||
|
||||
"What do you need me to do?" He asked.
|
||||
|
||||
***
|
||||
|
||||
Emily breathed a huge sigh of relief. "Let's sit down somewhere," she said quietly.
|
||||
|
||||
As she finally entered the house, and they started making their way over to Ben's living room, she felt a kind of unease course through her body. It wasn't the *bad Saturday waffles* kind. She couldn't quite put her finger on what this feeling was, but she felt her heart beating faster when they sat down on a rickety, brown sofa.
|
||||
|
||||
She knew, of course, that Ben didn't enjoy this whole situation. She knew that he wasn't the best liar, and she knew that he didn't *enjoy* lying all that much either. But this was different, she thought to herself. Emily never understood what, if anything, Ben felt for her. It wasn't that he was secretive about his feelings, it's that she was incredibly bad at reading them. To her, it was weird that so many people automatically *assumed* that she was amazing at talking to people, making conversation, and understanding what other people want. But this wasn't really the case. While Emily *did* love hanging out with people, the part of her brain that was meant for understanding people's feelings was probably being repurposed to store excessive amounts of Ariana Grande quotes. And it made her feel bad, too, because her best friend Ben was absolutely *packed* with feelings.
|
||||
|
||||
While poking at a small hole in the brown fabric she was sitting on, she recalled a situation from a few months ago. She and Ben were in the park, and there was some sort of spring festival going on. She had dragged him out to it because, even though she didn't necessarily *like* taking this role in his life, she'd often try to take him out of his shell and help him fight his anxiety. During that festival, he had a full-on *panic attack* (the kind of thing that she, as an avid Ariana Grande listener, did not understand), which caused him to run off and hide.
|
||||
|
||||
Was this really such a good idea?
|
||||
|
||||
"Okay, so," she said and let out a big sigh. "Let's talk relationship. What kind of boyfriend do you want to be?"
|
||||
|
||||
"I'm sorry?" He said, flustered.
|
||||
|
||||
"Well, I didn't tell my aunt that many lies about you, so the whole thing is pretty open. You can be super caring, or, you know, the bad boy type."
|
||||
|
||||
"The *bad boy type*?"
|
||||
|
||||
"Yea, like, uncaring and aloof, you know? Maybe wear a leather jacket."
|
||||
|
||||
"A leather- have you *met me*?" He responded in playful disgust.
|
||||
|
||||
"Okay, super caring it is, then," she laughed and moved her hands around in the air as if writing something down on a giant, invisible notebook.
|
||||
|
||||
Honestly, *super caring* was exactly the kind of boyfriend that she actually wanted. Of course, she would never say this out loud, but occasionally she dreamed of the perfect storybook romance. *Romeo and Juliet*, just without all the tragic stuff. Just like that one Taylor Swift song. While she'd fooled around with some of her girlfriends once or twice, she'd never actually had a relationship with anyone, especially not a guy. She didn't really know why, either. She briefly wondered if any guys had ever been visibly into her. Maybe she'd just missed it.
|
||||
|
||||
She'd also never admit *this*, of course, but Ben seemed like a fairly good candidate for the position of the super caring boyfriend. He was innocent, sweet, and he had the mane of an extremely gentle lion.
|
||||
|
||||
Uncomfortable silence had set in between the two, as it sometimes seemed to do. It didn't help that Emily had one of those weird thoughts again. Very occasionally, she'd have this intrusive image in her head: Ben, lion-like as he looked, not-so-gently on top of her. Sometimes he'd touch her breasts; sometimes they'd be kissing. Was she sexualizing her friendship? Maybe. Was that bad? She didn't know. She also didn't know if she cared yet. After all, she didn't *mean to*. It just kind of happened every now and again. If anything, didn't that speak to her fondness of Ben?
|
||||
|
||||
In an attempt to quickly change the subject on her mind, she started telling a story about her aunt.
|
||||
|
||||
"You're going to *love* my aunt," she said sarcastically. He looked at her with a sense of dread in his eyes. "Okay, one time, we were at this restaurant, the whole family all packed into this corner booth, and she would not stop pestering the poor waiter with question after question about the most ridiculous stuff! Every time she waved him back over to our table, he looked more and more tired of her shit."
|
||||
|
||||
"That's actually kind of horrifying," he responded and shook his head slowly.
|
||||
|
||||
"Right?"
|
||||
|
||||
# Chapter 2
|
||||
In the early evening, Ben found himself sitting at a big dinner table, straight across from an overly cheerful looking lady. If he had to guess, Em's aunt was probably around fifty-five years old, maybe a little older. She was slightly hunched over the table, resting one of her arms on it. *That's not how you sit at a table, young man*, he heard his own aunt's voice echoing in his head. Clearly, Emily's aunt didn't care, and from what he'd been told, this wasn't surprising.
|
||||
|
||||
When Emily's mom came into the room from the kitchen, she was carrying a large tray that held a variety of sweet pastries and cookies. Homemade, Ben assumed, waiting to bite into one of those chocolate croissants. Emily's mom set the tray down in the center of the table and pointed at it with an open hand as if to say *There you go, dig in*. So Emily and her sister did. After they finished selecting something they liked, Ben also felt comfortable taking a croissant.
|
||||
|
||||
A chocolate cookie in her delicate fingers, Emily's aunt turned to Emily. "So," she began while raising her thickly overdrawn, black eyebrows. "How have you been, my love?"
|
||||
|
||||
"Well, school's been going pretty well. I've only gotten good grades this semester, and my classes have been bearable."
|
||||
|
||||
Her aunt started smiling wide. "A perfect student as always! I expected nothing less of you, dear."
|
||||
|
||||
Emily provocatively rolled her eyes and sighed. Her aunt didn't seem affected by that at all. Instead, she continued smiling as she bit into her cookie. "And you, love?"
|
||||
|
||||
Confused for a second, Ben realized that she was talking to him now.
|
||||
|
||||
"Me? Oh, well," he stuttered. "School is also going great for me. Emily and I are pretty much on the same level in terms of grades and stuff."
|
||||
|
||||
"On the same level, you say? Maybe that's why you two get along so well! For years now, I've been *absolutely positive* that you two would make the cutest couple. And now it's *finally* happened, God bless."
|
||||
|
||||
Emily sighed, louder this time. Ben let out a stifled chuckle. *I wish*, he thought to himself.
|
||||
|
||||
***
|
||||
|
||||
As the conversation continued over dinner, followed by coffee, Ben felt himself zoning out from time to time. As he continued to observe Em and her aunt conversing, he felt his mind wander to a different world without his control.
|
||||
|
||||
A world where him and Em really *were* a couple. A world where, against all odds, they'd happily been together for years, with their own apartment, with floor-length windows and a balcony. They'd sit outside in the evenings, eating ice cream and sipping on cocktails. They would laugh and share stories of their day while watching the sunset over the park. They'd go into town on the weekends and eat at that little Italian place he keeps wanting to go to. They'd never fight anymore, because they'd be happy. He'd never cry alone, never wonder why he was too *stupid* to tell her how he felt.
|
||||
|
||||
Emily grabbed his hand. "We're going upstairs now," she said and got up from her chair.
|
||||
|
||||
Even though he knew it was fake; even though he knew that her hand in his meant *nothing*, it felt good. He craved contact like this, with someone he really cared about. He'd hug Emily more if it wasn't for his fear of being overbearing. Of being a nuisance. Why did he have to feel that way?
|
||||
|
||||
Emily dragged Ben behind her as she walked up the stairs, her palm still resting in his. When they got to the door of her room, she still hadn't let go of his hand. Why? Was Ben just reading into things again, or did she *enjoy* holding his hand? *Surely not. She'd never enjoy that*, he told himself. Then, as he frequently did, he told himself to stop telling himself things like that.
|
||||
|
||||
Emily finally let go of his hand upon entering her room. This was one of Ben's favorite places to be. Sometimes, he'd imagine him and Em cuddled up together on her bed, sharing a blanket, watching a movie or playing *GTA*.
|
||||
|
||||
He thought about this kind of thing a lot. Of course, he also thought a lot about the fact that he thought about this kind of thing so frequently. Was it bad to have these thoughts? Was he risking ruining his perfect friendship with Emily by making some big romance out of it in his head? Was it unfair to her to keep quiet about it? As they sat down next to each other on the bed, he tried to let these thoughts fade.
|
||||
|
||||
"Thank you *so damn much*, man," Emily said and let out a sigh of relief. "What a nightmare."
|
||||
|
||||
"Oh come on, it wasn't *that* bad."
|
||||
|
||||
"Did you hear what she *said*?" Emily put on a very bad, fake British accent. "I was *absolutely positive*," she mocked. "*My dear.*"
|
||||
|
||||
Ben couldn't help but laugh. "She's not that bad! I thought she was nice."
|
||||
|
||||
"Oh shut up, I *know* you." Did she? "People like her drive you *mad*! You never miss out on an opportunity to hide in your room. You don't *like* her."
|
||||
|
||||
Maybe she did know him. And maybe it was this realization that made him unable to think about the words flying out of his mouth. He let out a quiet, but emotional sigh, and said "I like *you*, though."
|
||||
|
||||
Emily turned and looked into his eyes. As he stared back, he could see a tiny reflection of his face in her brown irises. "I like you too, Ben. You know that," she said.
|
||||
|
||||
Maybe she didn't know him after all. He focused intensely on her face. What if this was the moment to be honest? What if, in the light of this fake relationship, he could finally be true to how he felt? Anxiety boiled up inside him. This was a panic attack just waiting to happen. But he had to try. Right?
|
||||
|
||||
"No," he said and gently took her hand. "I *really* like you, Em."
|
|
@ -1,172 +1,172 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 📅 Jed's Things to Avoid in Life
|
||||
summary: "Jed's rules are clear: No relationships. They interfere too much with his life, and he's not made for them anyway. But then, he sees his old crush from school in his hometown. Will he break his own rules for Davy?"
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
mature: true
|
||||
reedsy: https://blog.reedsy.com/creative-writing-prompts/contests/90/submissions/63882/
|
||||
discuss: https://twitter.com/Ellpeck/status/1385686796911185920
|
||||
---
|
||||
|
||||
Jed didn't do relationships. That was just one of his rules. Actually, it had become such an important rule to him that he added it to his very official, *highly* scientific List of Things to Avoid in Life. They were too complicated, and the touchy-feely stuff usually left him feeling inadequate about his ability to be there for someone. He also just didn't have the time, with his fifty-hour work week and all that. So not wasting his time trying to care for another person, especially considering that they'd probably notice pretty quickly how little he was able to care for them and ultimately leave him to be on his own again. So why bother, right?
|
||||
|
||||
He was sitting on a crowded, noisy train on his way to visit his parents in his childhood hometown. He didn't necessarily enjoy going there again, but this weekend was his mom's birthday, and he loved her too much to skip it. Even though his grandma would also be there, who he had a particular grudge with after finding out a few years ago about her dislike of a *pretty important* part of his life. So he wasn't particularly looking forward to talking to her about "the girls she envisions him marrying."
|
||||
|
||||
He looked out the window, the lush, pine-plastered mountains in the distance slowly creeping by, and imagined what it would be like if he really *was* as much into girls as his grandma wished he was. It's not like he hadn't thought about it. Of course, it would be easier for him to be straight. In fact, maybe his rules about relationships were only so airtight because he was afraid of being bullied. He didn't enjoy the thought of holding hands with his boyfriend, only to be attacked by some idiot in an alley. But his other reasons were good, too, right? He *was* a little emotionally unavailable at times. He *did* have that horrible work week. *Yes*, he thought to himself. *Those are good enough reasons to avoid the perfect, storybook romance you dreamed of as a kid, damn it.*
|
||||
|
||||
After leaving the train, he stopped in the middle of the platform and looked around to get his bearings again. Out of the corner of his eye, he noticed something odd. He turned to face the front window of a small bakery, the glass protecting delicious looking pastries and cakes that were quietly sitting in a large vitrine. But that wasn't the odd thing.
|
||||
|
||||
He started closely inspecting the head of the person standing behind the register, currently handing a glazed donut to an old lazy. After a few seconds, the person turned in his direction, and started looking directly at him. And there he was, standing in the middle of a train station, locking eyes with the *last* person he wanted to see in this town. He smiled and waved awkwardly, and the person behind the register did the same, before turning back to the old lady and finishing their transaction.
|
||||
|
||||
Jed, clearly having lost his mind, thought it would only be right to go inside and say hello. A little bell that was mounted behind the door rang. Now, he was standing right in front of him. His long, wavy brown hair had the same elegance as it did the last time Jed saw him, as if nothing had changed. Davy must've been sat in a time capsule for the last four years, because he still looked exactly as beautiful as he did all those years ago at school. No, better. Davy had broad shoulders and a wide frame. His arms were thick and muscular and Jed imagined them again, wrapped around his body, warming him. Protecting him.
|
||||
|
||||
"Jed! I didn't know you still lived in town," he said with a smile that penetrated all of Jed's defenses.
|
||||
|
||||
"I don't, actually," he stuttered. "I'm visiting my parents."
|
||||
|
||||
"Ah, that makes sense. Train station." Davy laughed awkwardly and pushed the hair out of his face with his hand. His motions were smooth and soft, and Jed couldn't help but notice the veins in his arms twitching as he moved his hands. *Jesus Christ*, he said to himself. *Get a grip.*
|
||||
|
||||
"How have you been?" Davy asked and raised an eyebrow.
|
||||
|
||||
"I've been pretty good, actually," Jed mumbled, still mesmerized by Davy's movements. The grip clearly hadn't been gotten yet. "I'm working at a pretty big software company."
|
||||
|
||||
"That's awesome," Davy said with a very real, supportive air of enthusiasm.
|
||||
|
||||
"And you?"
|
||||
|
||||
"Been working here to help with uni. That shit's really expensive, man." Davy chuckled.
|
||||
|
||||
Jed nodded his head slightly. "Yea, I can imagine," he said.
|
||||
|
||||
"Anyway, it's cool that you're here. Do you maybe want to catch up some time?"
|
||||
|
||||
Jed froze. *Oh my God*, he thought. Had Davy really just asked him on a date? Okay, well. Not a *proper* date, but...
|
||||
|
||||
"Uh, yea, that sounds great," he mumbled. If Davy was a mirror, he'd probably see his entire face turn into a tomato right now. *Oh, God.* "I'm free the whole weekend," he continued.
|
||||
|
||||
They exchanged phone numbers, and Jed breathed a sigh of relief when he exited the bakery. Thankfully, Davy didn't seem to have noticed how awkwardly Jed was acting around him. Was he even acting that awkwardly? Possibly. Probably.
|
||||
|
||||
***
|
||||
|
||||
Only a few days later, Jed arrived at a coffee shop that he used to go to with his friends after school sometimes. It was small, filled with small nooks with comfortable looking armchairs that had colorful blankets thrown over them. Taking in the romance that this place clearly emitted, he sighed to himself. *Oh God, this is a* proper *date, isn't it?*
|
||||
|
||||
He waited in the entryway of the café until Davy arrived. And *boy*, did he arrive. He walked into the room wearing a jean jacket over a black logo tee and jeans. His hair was blowing in the wind let in by the open door, and it reminded Jed of their first encounter at the train station. The whole outfit made Davy seem strong. For a second, Jed imagined what it would be like to be scooped up by his strong, muscular arms like a princess. Like a *prince*.
|
||||
|
||||
*Get a grip*, he thought to himself.
|
||||
|
||||
"Hey man," Davy said with a smile as he saw Jed. *Hey, 'man'?*, he repeated in his head.
|
||||
|
||||
"Hey Davy," said Jed with an awkward half-smile. He tried to wipe it off. "You look," he started, but he didn't know how to finish.
|
||||
|
||||
"Gay?" Davy suggested. "I know. I just love this jacket so much."
|
||||
|
||||
"That's not-", Jed stuttered. "I didn't ... you look *good*." He hesitated. Why did he *say* that?
|
||||
|
||||
"Thanks. You don't look too bad yourself," Davy said and started making his way towards one of the seating nooks. He brushed Jed's arm with his own while passing him, and it made that place tingle with... with something.
|
||||
|
||||
Jed realized that he didn't even know for sure if Davy was into guys. He wondered for a second if that comment about his jacket was confirmation that he was, in fact, gay. Was anything he'd done so far confirmation that he was?
|
||||
|
||||
A weird feeling of unease creeped up in Jed's chest, and it immediately entered his heart. *What if he's not even into guys?*, he thought to himself. He didn't do relationships anyway, though, so why would it matter -- right? They were too complicated, too time-consuming, and too draining of the small amount of emotions that Jed had. So it was of no value to know whether Davy was into him or not.
|
||||
|
||||
He really enjoyed the idea though. As he watched Davy sit down on a sofa in one of the nooks, he imagined what it'd be like to be on that sofa with him. Sitting next to him. Close. Kissing him. Davy's hand moving closer to Jed's--
|
||||
|
||||
"Are you coming?", Davy called and waved. *Oh God*, Jed thought to himself. *Hopefully not.*
|
||||
|
||||
Jed started walking towards him, and Davy started patting the spot next to him on the sofa. He wanted Jed to sit next to him. *Great.*
|
||||
|
||||
Of course, being the gentleman he was, it was only right of Jed to actually go ahead and sit down next to Davy. That was the only reason, *of course*.
|
||||
|
||||
They both ordered drinks (hot chocolate) and food (cheesecake and apple pie) and started chatting about how they'd been since school. Davy talked about his university courses and the bakery job and how he'd sometimes see his old friends at the train station, and Jed was *fascinated*. It wasn't that Davy's stories were actually *fascinating*, but somehow, because *he* was the one telling them, they seemed more alive than Jed ever thought a story could be.
|
||||
|
||||
When Jed started talking about his job, about the long work hours and about his family, Davy turned a bit to face him. Now they were sitting closer, almost opposite one another, and Davy's gaze seemed to be locked onto Jed's eyes while he told his stories. He'd never met someone, Jed thought to himself, who seemed so genuinely interested in his life. Somehow, the two of them were just fascinated with each other, it seemed. But Jed's rule was clear: *No relationships*. They were a waste of time, and that was a final, reasonable, and educated decision.
|
||||
|
||||
That was, of course, until they started talking about Jed's homophobic grandma. As soon as he mentioned that his grandma didn't 'approve' of his sexuality, Davy's smile faded, and he rolled his eyes. The sight made Jed chuckle.
|
||||
|
||||
"Relatable?", Jed asked with a tiny grin.
|
||||
|
||||
Davy tutted. "Oh God, don't get me *started*."
|
||||
|
||||
He shifted a little on the sofa, and they were sitting even closer to each other now. Was he doing this on purpose?
|
||||
|
||||
"My mom's the same way."
|
||||
|
||||
"Your *mom*? That's terrible!", Jed hissed.
|
||||
|
||||
"Eh, I've been getting by alright. I don't need her, you know? It's her loss." Davy began smiling again. "I've got enough people in my life who support me."
|
||||
|
||||
"That's good," Jed responded. Overwhelmed with the flood of endearing sentiments rushing through his chest -- the homophobic mom, the sweet sentiment about Davy's chosen family, and just how close to each other they were sitting right now -- Jed couldn't stop himself from saying more. "I'd support you too, you know."
|
||||
|
||||
"You know what," Davy began. *Oh God*, Jed thought to himself. This was it. He'd ruined it. *You're getting a bit creepy*, that's what Davy was about to say. Right? He'd said too much. But Davy's smile didn't fade. Instead, he chuckled and put his hand on Jed's shoulder.
|
||||
|
||||
"You're great to hang out with, Jed," Davy continued. "But I really have to go now, sadly. I really want to see you again, though."
|
||||
|
||||
Jed's cheeks warmed up, and he began to smile again. "Me, too," he said shakily.
|
||||
|
||||
Over the next few days, Jed kept daydreaming about Davy. His cute smile, his wavy hair and his muscular, strong arms. He kept picturing, over and over, how Davy grabbed his arm when they sat so close in the café. He should've kissed him then and there. No, it would've been too soon. Plus, they had another date lined up. Because he hadn't seen town in a while, Davy came up with the idea of hiking to the top of the nearby mountain and looking down at the cityscape from there.
|
||||
|
||||
But maybe he shouldn't get closer to Davy, he thought. He didn't want to give him the wrong idea. His list of rules was very strict, and Jed intended to continue following it. No relationships, because they are too complicated and time-consuming. But Davy could've happily consumed all of his time without Jed even remembering that his list of rules *exists*.
|
||||
|
||||
***
|
||||
|
||||
There he was. Strong as always, wearing a t-shirt that made his muscular upper arms even more pronounced than usual. Today, his long, silky hair wasn't flowing over his shoulders, though. He had tied it up into a ponytail, presumably so it wouldn't bother him during their hike.
|
||||
|
||||
Jed approached him on the parking lot close to the hike trail leading up the mountain, and Davy turned around slowly.
|
||||
|
||||
"Hey," he said in a rough voice. He cleared his throat, before saying "hey" again, less raspy this time.
|
||||
|
||||
"Hi. I'm excited!" Jed blurted out with an unusual amount of confidence. *The rules, damn it*, he thought to himself. *Get a grip.*
|
||||
|
||||
"Me too. I packed some snacks for us, as well," said Davy and pointed to his backpack. He shifted his upper body and laughed, causing what sounded to be loose food items to rustle in the bag.
|
||||
|
||||
Halfway up the trail, Jed started getting exhausted. It wasn't that he was out of shape (he'd been working out occasionally because of the part of his List of Things to Avoid in Life that read *getting out of shape*, of course), but something about this hike was different to him. Stopping on the trail, he grabbed a bottle of water out of his backpack and started gulping it down without hesitation. Davy stopped as well, and observed Jed as he almost finished the entire bottle.
|
||||
|
||||
"Want to take a break?", he asked slyly.
|
||||
|
||||
"Shut up, I can do this!", Jed blurted out without much thought. *Oops.* "I'm just-"
|
||||
|
||||
Davy cut him off. "Well, I know you can, but you can also relax with me for a little while."
|
||||
|
||||
Relaxing sounded like a great idea to Jed. He wiped his mouth and chin with his forearm and looked over at Davy, who had already found a nice bit of grass to sit down on. *Laying down on the grass together*, he thought, remembering this very fantasy having been stuck in his head for the last few days. *Of course. Damn it.*
|
||||
|
||||
Jed walked up to Davy and looked down questioningly. Davy looked back up at him and smiled.
|
||||
|
||||
"Come sit," he said with a grin, pointing to the ground right next to him. Jed did as he was told.
|
||||
|
||||
And now, there they were, just like in Jed's *stupid* fantasies. Sitting next to each other, looking out over the forest and a small part of town, with Jed feeling the cool, green grass underneath him.
|
||||
|
||||
"You know," Davy began. "I used to think that you were kind of weird. In school, you know. I only realized afterwards that..." He hesitated. Jed turned his head to see the expression on Davy's face, but there wasn't much being expressed there at all. Eventually, Davy continued.
|
||||
|
||||
"I think I realized that I had the tiniest bit of a crush on you."
|
||||
|
||||
On... *what*? Jed's heart skipped a beat. What had Davy just said? Clearly, Davy was out of his mind. Or Jed was. Was he dreaming? Was he passed out from exhaustion somewhere, laying on the path, with Davy wondering what he'd gotten himself into? Jed shook his head. *No.* This seemed to real to be a dream.
|
||||
|
||||
"You... you did?", Jed stuttered. Davy chuckled.
|
||||
|
||||
"I think so, yea. You were always kind of cute, and seeing you at the train station the other day... I don't know, it felt like a sign."
|
||||
|
||||
*A sign*, Jed thought to himself. He could kind of see that. The hunky, adorable student who worked in a bakery, with his long hippy-like hair, believing in *signs* and probably *soulmates* and what have you. This made sense to Jed. But the fact that Davy was saying all of this to *him* made no sense at all.
|
||||
|
||||
"Are you serious? I--", Jed paused, trying to formulate a coherent sentence in his mind. Davy was looking at him with a sense of desperation in his eyes. *Tell me that you like me too*, they seemed to say.
|
||||
|
||||
At this point, Jed went over the options in his mind. The rules, the meeting at the train station, the *coincidence* of it all. Maybe he believed in signs, too. Maybe he believed that, out of all the people he could've met that day, Davy was just the perfect one. Maybe, he thought to himself, his rules didn't actually matter that much after all.
|
||||
|
||||
"I actually really liked you too. In school. I always saw you with all of those girls and I thought, you know. I thought I'd never have a chance. Especially since you seemed so..." Davy cut him off.
|
||||
|
||||
"So straight?", he said and laughed.
|
||||
|
||||
"I guess, yea."
|
||||
|
||||
"Well, I'm not. I mean, I am. I'm bi, actually," he explained.
|
||||
|
||||
"That makes sense," Jed responded, not really sure what else to say. They were both silent for a moment, but their gazes were still interlocked. They were sitting close enough together now for Jed to feel both of their breathing warming up the air between them.
|
||||
|
||||
"Do you want to..." Davy began, but he paused. Jed wanted a lot of things right now. He imagined moving closer to Davy, putting his hand on his thigh, maybe lower, deeper, and going through Davy's hair with his hand. He didn't, however, know what Davy wanted. So he didn't do anything.
|
||||
|
||||
"Can I kiss you?", Davy asked after an uncomfortably long silence. Jed didn't answer with words -- how could he possibly answer that question without melting into a puddle then and there -- but apparently, his wide smile was enough indication to Davy that Jed *did* want to kiss him.
|
||||
|
||||
Davy moved in closer, grasping Jed's hip with one hand, and as Davy leaned in closer with his head, Jed could see the veins in his arm twitching as he moved.
|
||||
|
||||
Jed closed his eyes, and he felt Davy's lips touch his own. He felt him reaching around Jed's body with his other hand, fully enclosing him in his strong embrace now. It felt good. Jed wanted to continue, forever, staying here and kissing Davy until the end of time.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 📅 Jed's Things to Avoid in Life
|
||||
description: "Jed's rules are clear: No relationships. They interfere too much with his life, and he's not made for them anyway. But then, he sees his old crush from school in his hometown. Will he break his own rules for Davy?"
|
||||
tags: [Short Stories]
|
||||
book: true
|
||||
mature: true
|
||||
reedsy: https://blog.reedsy.com/creative-writing-prompts/contests/90/submissions/63882/
|
||||
discuss: https://twitter.com/Ellpeck/status/1385686796911185920
|
||||
---
|
||||
|
||||
Jed didn't do relationships. That was just one of his rules. Actually, it had become such an important rule to him that he added it to his very official, *highly* scientific List of Things to Avoid in Life. They were too complicated, and the touchy-feely stuff usually left him feeling inadequate about his ability to be there for someone. He also just didn't have the time, with his fifty-hour work week and all that. So not wasting his time trying to care for another person, especially considering that they'd probably notice pretty quickly how little he was able to care for them and ultimately leave him to be on his own again. So why bother, right?
|
||||
|
||||
He was sitting on a crowded, noisy train on his way to visit his parents in his childhood hometown. He didn't necessarily enjoy going there again, but this weekend was his mom's birthday, and he loved her too much to skip it. Even though his grandma would also be there, who he had a particular grudge with after finding out a few years ago about her dislike of a *pretty important* part of his life. So he wasn't particularly looking forward to talking to her about "the girls she envisions him marrying."
|
||||
|
||||
He looked out the window, the lush, pine-plastered mountains in the distance slowly creeping by, and imagined what it would be like if he really *was* as much into girls as his grandma wished he was. It's not like he hadn't thought about it. Of course, it would be easier for him to be straight. In fact, maybe his rules about relationships were only so airtight because he was afraid of being bullied. He didn't enjoy the thought of holding hands with his boyfriend, only to be attacked by some idiot in an alley. But his other reasons were good, too, right? He *was* a little emotionally unavailable at times. He *did* have that horrible work week. *Yes*, he thought to himself. *Those are good enough reasons to avoid the perfect, storybook romance you dreamed of as a kid, damn it.*
|
||||
|
||||
After leaving the train, he stopped in the middle of the platform and looked around to get his bearings again. Out of the corner of his eye, he noticed something odd. He turned to face the front window of a small bakery, the glass protecting delicious looking pastries and cakes that were quietly sitting in a large vitrine. But that wasn't the odd thing.
|
||||
|
||||
He started closely inspecting the head of the person standing behind the register, currently handing a glazed donut to an old lazy. After a few seconds, the person turned in his direction, and started looking directly at him. And there he was, standing in the middle of a train station, locking eyes with the *last* person he wanted to see in this town. He smiled and waved awkwardly, and the person behind the register did the same, before turning back to the old lady and finishing their transaction.
|
||||
|
||||
Jed, clearly having lost his mind, thought it would only be right to go inside and say hello. A little bell that was mounted behind the door rang. Now, he was standing right in front of him. His long, wavy brown hair had the same elegance as it did the last time Jed saw him, as if nothing had changed. Davy must've been sat in a time capsule for the last four years, because he still looked exactly as beautiful as he did all those years ago at school. No, better. Davy had broad shoulders and a wide frame. His arms were thick and muscular and Jed imagined them again, wrapped around his body, warming him. Protecting him.
|
||||
|
||||
"Jed! I didn't know you still lived in town," he said with a smile that penetrated all of Jed's defenses.
|
||||
|
||||
"I don't, actually," he stuttered. "I'm visiting my parents."
|
||||
|
||||
"Ah, that makes sense. Train station." Davy laughed awkwardly and pushed the hair out of his face with his hand. His motions were smooth and soft, and Jed couldn't help but notice the veins in his arms twitching as he moved his hands. *Jesus Christ*, he said to himself. *Get a grip.*
|
||||
|
||||
"How have you been?" Davy asked and raised an eyebrow.
|
||||
|
||||
"I've been pretty good, actually," Jed mumbled, still mesmerized by Davy's movements. The grip clearly hadn't been gotten yet. "I'm working at a pretty big software company."
|
||||
|
||||
"That's awesome," Davy said with a very real, supportive air of enthusiasm.
|
||||
|
||||
"And you?"
|
||||
|
||||
"Been working here to help with uni. That shit's really expensive, man." Davy chuckled.
|
||||
|
||||
Jed nodded his head slightly. "Yea, I can imagine," he said.
|
||||
|
||||
"Anyway, it's cool that you're here. Do you maybe want to catch up some time?"
|
||||
|
||||
Jed froze. *Oh my God*, he thought. Had Davy really just asked him on a date? Okay, well. Not a *proper* date, but...
|
||||
|
||||
"Uh, yea, that sounds great," he mumbled. If Davy was a mirror, he'd probably see his entire face turn into a tomato right now. *Oh, God.* "I'm free the whole weekend," he continued.
|
||||
|
||||
They exchanged phone numbers, and Jed breathed a sigh of relief when he exited the bakery. Thankfully, Davy didn't seem to have noticed how awkwardly Jed was acting around him. Was he even acting that awkwardly? Possibly. Probably.
|
||||
|
||||
***
|
||||
|
||||
Only a few days later, Jed arrived at a coffee shop that he used to go to with his friends after school sometimes. It was small, filled with small nooks with comfortable looking armchairs that had colorful blankets thrown over them. Taking in the romance that this place clearly emitted, he sighed to himself. *Oh God, this is a* proper *date, isn't it?*
|
||||
|
||||
He waited in the entryway of the café until Davy arrived. And *boy*, did he arrive. He walked into the room wearing a jean jacket over a black logo tee and jeans. His hair was blowing in the wind let in by the open door, and it reminded Jed of their first encounter at the train station. The whole outfit made Davy seem strong. For a second, Jed imagined what it would be like to be scooped up by his strong, muscular arms like a princess. Like a *prince*.
|
||||
|
||||
*Get a grip*, he thought to himself.
|
||||
|
||||
"Hey man," Davy said with a smile as he saw Jed. *Hey, 'man'?*, he repeated in his head.
|
||||
|
||||
"Hey Davy," said Jed with an awkward half-smile. He tried to wipe it off. "You look," he started, but he didn't know how to finish.
|
||||
|
||||
"Gay?" Davy suggested. "I know. I just love this jacket so much."
|
||||
|
||||
"That's not-", Jed stuttered. "I didn't ... you look *good*." He hesitated. Why did he *say* that?
|
||||
|
||||
"Thanks. You don't look too bad yourself," Davy said and started making his way towards one of the seating nooks. He brushed Jed's arm with his own while passing him, and it made that place tingle with... with something.
|
||||
|
||||
Jed realized that he didn't even know for sure if Davy was into guys. He wondered for a second if that comment about his jacket was confirmation that he was, in fact, gay. Was anything he'd done so far confirmation that he was?
|
||||
|
||||
A weird feeling of unease creeped up in Jed's chest, and it immediately entered his heart. *What if he's not even into guys?*, he thought to himself. He didn't do relationships anyway, though, so why would it matter -- right? They were too complicated, too time-consuming, and too draining of the small amount of emotions that Jed had. So it was of no value to know whether Davy was into him or not.
|
||||
|
||||
He really enjoyed the idea though. As he watched Davy sit down on a sofa in one of the nooks, he imagined what it'd be like to be on that sofa with him. Sitting next to him. Close. Kissing him. Davy's hand moving closer to Jed's--
|
||||
|
||||
"Are you coming?", Davy called and waved. *Oh God*, Jed thought to himself. *Hopefully not.*
|
||||
|
||||
Jed started walking towards him, and Davy started patting the spot next to him on the sofa. He wanted Jed to sit next to him. *Great.*
|
||||
|
||||
Of course, being the gentleman he was, it was only right of Jed to actually go ahead and sit down next to Davy. That was the only reason, *of course*.
|
||||
|
||||
They both ordered drinks (hot chocolate) and food (cheesecake and apple pie) and started chatting about how they'd been since school. Davy talked about his university courses and the bakery job and how he'd sometimes see his old friends at the train station, and Jed was *fascinated*. It wasn't that Davy's stories were actually *fascinating*, but somehow, because *he* was the one telling them, they seemed more alive than Jed ever thought a story could be.
|
||||
|
||||
When Jed started talking about his job, about the long work hours and about his family, Davy turned a bit to face him. Now they were sitting closer, almost opposite one another, and Davy's gaze seemed to be locked onto Jed's eyes while he told his stories. He'd never met someone, Jed thought to himself, who seemed so genuinely interested in his life. Somehow, the two of them were just fascinated with each other, it seemed. But Jed's rule was clear: *No relationships*. They were a waste of time, and that was a final, reasonable, and educated decision.
|
||||
|
||||
That was, of course, until they started talking about Jed's homophobic grandma. As soon as he mentioned that his grandma didn't 'approve' of his sexuality, Davy's smile faded, and he rolled his eyes. The sight made Jed chuckle.
|
||||
|
||||
"Relatable?", Jed asked with a tiny grin.
|
||||
|
||||
Davy tutted. "Oh God, don't get me *started*."
|
||||
|
||||
He shifted a little on the sofa, and they were sitting even closer to each other now. Was he doing this on purpose?
|
||||
|
||||
"My mom's the same way."
|
||||
|
||||
"Your *mom*? That's terrible!", Jed hissed.
|
||||
|
||||
"Eh, I've been getting by alright. I don't need her, you know? It's her loss." Davy began smiling again. "I've got enough people in my life who support me."
|
||||
|
||||
"That's good," Jed responded. Overwhelmed with the flood of endearing sentiments rushing through his chest -- the homophobic mom, the sweet sentiment about Davy's chosen family, and just how close to each other they were sitting right now -- Jed couldn't stop himself from saying more. "I'd support you too, you know."
|
||||
|
||||
"You know what," Davy began. *Oh God*, Jed thought to himself. This was it. He'd ruined it. *You're getting a bit creepy*, that's what Davy was about to say. Right? He'd said too much. But Davy's smile didn't fade. Instead, he chuckled and put his hand on Jed's shoulder.
|
||||
|
||||
"You're great to hang out with, Jed," Davy continued. "But I really have to go now, sadly. I really want to see you again, though."
|
||||
|
||||
Jed's cheeks warmed up, and he began to smile again. "Me, too," he said shakily.
|
||||
|
||||
Over the next few days, Jed kept daydreaming about Davy. His cute smile, his wavy hair and his muscular, strong arms. He kept picturing, over and over, how Davy grabbed his arm when they sat so close in the café. He should've kissed him then and there. No, it would've been too soon. Plus, they had another date lined up. Because he hadn't seen town in a while, Davy came up with the idea of hiking to the top of the nearby mountain and looking down at the cityscape from there.
|
||||
|
||||
But maybe he shouldn't get closer to Davy, he thought. He didn't want to give him the wrong idea. His list of rules was very strict, and Jed intended to continue following it. No relationships, because they are too complicated and time-consuming. But Davy could've happily consumed all of his time without Jed even remembering that his list of rules *exists*.
|
||||
|
||||
***
|
||||
|
||||
There he was. Strong as always, wearing a t-shirt that made his muscular upper arms even more pronounced than usual. Today, his long, silky hair wasn't flowing over his shoulders, though. He had tied it up into a ponytail, presumably so it wouldn't bother him during their hike.
|
||||
|
||||
Jed approached him on the parking lot close to the hike trail leading up the mountain, and Davy turned around slowly.
|
||||
|
||||
"Hey," he said in a rough voice. He cleared his throat, before saying "hey" again, less raspy this time.
|
||||
|
||||
"Hi. I'm excited!" Jed blurted out with an unusual amount of confidence. *The rules, damn it*, he thought to himself. *Get a grip.*
|
||||
|
||||
"Me too. I packed some snacks for us, as well," said Davy and pointed to his backpack. He shifted his upper body and laughed, causing what sounded to be loose food items to rustle in the bag.
|
||||
|
||||
Halfway up the trail, Jed started getting exhausted. It wasn't that he was out of shape (he'd been working out occasionally because of the part of his List of Things to Avoid in Life that read *getting out of shape*, of course), but something about this hike was different to him. Stopping on the trail, he grabbed a bottle of water out of his backpack and started gulping it down without hesitation. Davy stopped as well, and observed Jed as he almost finished the entire bottle.
|
||||
|
||||
"Want to take a break?", he asked slyly.
|
||||
|
||||
"Shut up, I can do this!", Jed blurted out without much thought. *Oops.* "I'm just-"
|
||||
|
||||
Davy cut him off. "Well, I know you can, but you can also relax with me for a little while."
|
||||
|
||||
Relaxing sounded like a great idea to Jed. He wiped his mouth and chin with his forearm and looked over at Davy, who had already found a nice bit of grass to sit down on. *Laying down on the grass together*, he thought, remembering this very fantasy having been stuck in his head for the last few days. *Of course. Damn it.*
|
||||
|
||||
Jed walked up to Davy and looked down questioningly. Davy looked back up at him and smiled.
|
||||
|
||||
"Come sit," he said with a grin, pointing to the ground right next to him. Jed did as he was told.
|
||||
|
||||
And now, there they were, just like in Jed's *stupid* fantasies. Sitting next to each other, looking out over the forest and a small part of town, with Jed feeling the cool, green grass underneath him.
|
||||
|
||||
"You know," Davy began. "I used to think that you were kind of weird. In school, you know. I only realized afterwards that..." He hesitated. Jed turned his head to see the expression on Davy's face, but there wasn't much being expressed there at all. Eventually, Davy continued.
|
||||
|
||||
"I think I realized that I had the tiniest bit of a crush on you."
|
||||
|
||||
On... *what*? Jed's heart skipped a beat. What had Davy just said? Clearly, Davy was out of his mind. Or Jed was. Was he dreaming? Was he passed out from exhaustion somewhere, laying on the path, with Davy wondering what he'd gotten himself into? Jed shook his head. *No.* This seemed to real to be a dream.
|
||||
|
||||
"You... you did?", Jed stuttered. Davy chuckled.
|
||||
|
||||
"I think so, yea. You were always kind of cute, and seeing you at the train station the other day... I don't know, it felt like a sign."
|
||||
|
||||
*A sign*, Jed thought to himself. He could kind of see that. The hunky, adorable student who worked in a bakery, with his long hippy-like hair, believing in *signs* and probably *soulmates* and what have you. This made sense to Jed. But the fact that Davy was saying all of this to *him* made no sense at all.
|
||||
|
||||
"Are you serious? I--", Jed paused, trying to formulate a coherent sentence in his mind. Davy was looking at him with a sense of desperation in his eyes. *Tell me that you like me too*, they seemed to say.
|
||||
|
||||
At this point, Jed went over the options in his mind. The rules, the meeting at the train station, the *coincidence* of it all. Maybe he believed in signs, too. Maybe he believed that, out of all the people he could've met that day, Davy was just the perfect one. Maybe, he thought to himself, his rules didn't actually matter that much after all.
|
||||
|
||||
"I actually really liked you too. In school. I always saw you with all of those girls and I thought, you know. I thought I'd never have a chance. Especially since you seemed so..." Davy cut him off.
|
||||
|
||||
"So straight?", he said and laughed.
|
||||
|
||||
"I guess, yea."
|
||||
|
||||
"Well, I'm not. I mean, I am. I'm bi, actually," he explained.
|
||||
|
||||
"That makes sense," Jed responded, not really sure what else to say. They were both silent for a moment, but their gazes were still interlocked. They were sitting close enough together now for Jed to feel both of their breathing warming up the air between them.
|
||||
|
||||
"Do you want to..." Davy began, but he paused. Jed wanted a lot of things right now. He imagined moving closer to Davy, putting his hand on his thigh, maybe lower, deeper, and going through Davy's hair with his hand. He didn't, however, know what Davy wanted. So he didn't do anything.
|
||||
|
||||
"Can I kiss you?", Davy asked after an uncomfortably long silence. Jed didn't answer with words -- how could he possibly answer that question without melting into a puddle then and there -- but apparently, his wide smile was enough indication to Davy that Jed *did* want to kiss him.
|
||||
|
||||
Davy moved in closer, grasping Jed's hip with one hand, and as Davy leaned in closer with his head, Jed could see the veins in his arm twitching as he moved.
|
||||
|
||||
Jed closed his eyes, and he felt Davy's lips touch his own. He felt him reaching around Jed's body with his other hand, fully enclosing him in his strong embrace now. It felt good. Jed wanted to continue, forever, staying here and kissing Davy until the end of time.
|
||||
|
||||
This was good. To Jed, it was the perfect place to be.
|
|
@ -1,190 +1,190 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 🤡 One Year of Tiny Life, and Cursed Comment Time
|
||||
summary: It's been exactly one year since I started working on my isometric Sims-style life simulation game Tiny Life, and since then, a lot has happened, especially in the realm of weird, funny and cursed comments in the code.
|
||||
tags: [Programming, Featured]
|
||||
discuss: https://ellpeck.itch.io/tiny-life/devlog/256839/one-year-of-tiny-life-and-cursed-comment-time
|
||||
---
|
||||
|
||||
On this day, exactly one year ago, I made my first commit to the Tiny Life repository. Since that first commit, which included some code for the isometric perspective that the game uses, Tiny Life has come *a long way*.
|
||||
|
||||
<img src="/blog/res/tiny_life_one_year/commit.png" width="100%">
|
||||
|
||||
If you don't recall just how long of a way it has come, or you don't even know about the game yet: Tiny Life is, as I wrote on its [itch page](https://ellpeck.itch.io/tiny-life):
|
||||
|
||||
> Tiny Life is a fun simulation game that tries to capture the essence of games like The Sims, but in an isometric pixelart style.
|
||||
>
|
||||
> In the game, you control a set of people that live together in a household. You take care of their daily needs, build their skills, forge new relationships... or just mess up their entire life in whatever way you can think of!
|
||||
|
||||
So, to celebrate, and because of a Twitter poll I did a while ago that made it clear that yall are interested in something like this, let's go through Tiny Life's current code and fish out some funny, cursed and weird code comments that just naturally come about when making a game that tries to simulate the personalities and behaviors of human people.
|
||||
|
||||
While this blog post *does* include a lot of programming-related humor, most of the comments are still funny and a bit ridiculous out of context, so you don't have to be a programmer to laugh along by any means.
|
||||
|
||||
<img src="/blog/res/tiny_life_one_year/search.png" width="100%">
|
||||
|
||||
That should do for now. *Oh, boy.* Note that I'll just be going through them using the order they appear in these search results, so the funniest ones won't be at the start or the end, but just... somewhere in between.
|
||||
|
||||
First up, this is one that most of you will probably find pretty relatable.
|
||||
```cs
|
||||
// we want people to clean dishes when they're hungry to make space for food
|
||||
Ai = {
|
||||
SolvedNeeds = new[] {NeedType.Hunger},
|
||||
}
|
||||
```
|
||||
|
||||
This one is for the introverts (to whom I most certainly belong) out there.
|
||||
```cs
|
||||
// we only want to visit someone when we're currently at home for long enough
|
||||
if (a)
|
||||
return i.Person.LotVisitCooldown <= TimeSpan.Zero && i.Person.LastVisitedLot == i.Person.HomeLot ? Valid : Hidden;
|
||||
|
||||
```
|
||||
|
||||
Teenagers should probably remember this one. Consent is (very unironically) important, yall!
|
||||
```cs
|
||||
// automatic romance interactions should only happen if we're already romantic towards each other
|
||||
return relationship?.RomanceLevel > 0 ? Valid : Hidden;
|
||||
```
|
||||
|
||||
Fair enough.
|
||||
```cs
|
||||
// eat food if we're hungry
|
||||
if (person.GetNeedPercentage(NeedType.Hunger) <= 0.5F && obj.ServingSize <= 1)
|
||||
return ActionType.Eat.Construct(person.GetHeldActionInfo());
|
||||
```
|
||||
|
||||
Especially in the city! Don't linger around too long, kids.
|
||||
```cs
|
||||
// move to the sidewalk once we're done driving
|
||||
var road = this.Map.GetClosestRoad(car.Position.ToPoint(), Map.RoadRadius + 1);
|
||||
```
|
||||
|
||||
You: Oh no, my car broke down!
|
||||
Me:
|
||||
```cs
|
||||
// if the driving fails, we always want to walk to the goal in the end
|
||||
return base.ShouldFail(completedAction, completion) && completedAction is not DriveAction;
|
||||
```
|
||||
|
||||
Do yall also do this thing where you're like "I cleaned *a single dish*, now I can take a break"?
|
||||
```cs
|
||||
// should we start to take a break between actions?
|
||||
if (this.OnBetweenActions(time, passedInGame, speed, current, completion)) {
|
||||
this.isBetweenActions = true;
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
It might be sad to hear, but this is something *you* have to do as well.
|
||||
```cs
|
||||
// we want to prioritize going to work over sleeping automatically
|
||||
if (this.StartedAutomatically && this.Person.Job != null && this.Person.Job.Type.IsTimeToWork(GameImpl.Instance.CurrentTime + TimeSpan.FromHours(1)))
|
||||
return CompletionType.Canceled;
|
||||
```
|
||||
|
||||
A bit creepy, don't you think?
|
||||
```cs
|
||||
// follow our partner until we reach them
|
||||
if (this.IsMain) {
|
||||
this.followTimer -= time.ElapsedGameTime;
|
||||
```
|
||||
|
||||
Jesus Christ, mom, how many more times do you want to tell me that *same story*?
|
||||
```cs
|
||||
// we add the recent social to the relationship of the recipient
|
||||
// so it represents an "I've heard this story already" list
|
||||
relationship.AddRecentSocial(action.Type);
|
||||
```
|
||||
|
||||
Also... fair enough.
|
||||
```cs
|
||||
// make lots more interesting if we have friends on them
|
||||
lot = Random.GetRandomWeightedEntry(lots, l => l.Type.GetVisitPriority(l, this.Person));
|
||||
```
|
||||
|
||||
It really *is* based on our mood how efficiently we work.
|
||||
```cs
|
||||
// if we're currently working, we should increase job performance based on our mood
|
||||
var performance = this.Person.Needs.Values.Count(n => n.Percentage >= 0.75F) * 0.004F;
|
||||
```
|
||||
|
||||
Does this also apply to *sleepovers*?
|
||||
```cs
|
||||
// the bed that we last slept in should be the one we try to sleep in again
|
||||
if (this.HasCategory(person, ObjectCategory.Bed) && categories.HasFlag(ObjectCategory.Bed) && this.Id == person.LastBedSleptIn)
|
||||
return 10;
|
||||
```
|
||||
|
||||
Fair... enough.
|
||||
```cs
|
||||
// pee puddles should be more disgusting
|
||||
DecorativeRating = f => f.Colors[0] == 1 ? -30 : -10
|
||||
```
|
||||
|
||||
For this one, I especially like that I chose to name the variable `naked`.
|
||||
```cs
|
||||
// if someone isn't wearing pants and they aren't romantic with us, we should get (them) embarrassed
|
||||
var naked = room.GetObjects<Person>()
|
||||
.Where(p => p != this && p.GetRelationship(this, false)?.RomancePercentage < 0.25F && !p.WornLayers.HasFlag(ClothesLayer.Pants))
|
||||
.ToArray();
|
||||
```
|
||||
|
||||
This comment is, of course, in the `Person.Die` method.
|
||||
```cs
|
||||
// make friends sad
|
||||
foreach (var rel in this.Relationships) {
|
||||
```
|
||||
|
||||
You: I'm bored!
|
||||
Me:
|
||||
```cs
|
||||
// if we don't have anything else to do, also try random actions
|
||||
if (this.person.ActionQueue.Count <= 0 && this.person.CurrentActions.Count <= 0)
|
||||
avail.AddRange(RandomActions);
|
||||
```
|
||||
|
||||
Drunk people, anyone?
|
||||
```cs
|
||||
// don't do stuff that's inappropriate here
|
||||
if (type.Settings.IsInappropriateElsewhere) {
|
||||
```
|
||||
|
||||
Am I wrong? I say no.
|
||||
```cs
|
||||
// the front door is the closest door to the mailbox that connects outside and inside
|
||||
var mailbox = this.GetObjects<Furniture>().FirstOrDefault(f => f.Type == FurnitureType.Mailbox);
|
||||
```
|
||||
|
||||
Oh no, I *really* hope it isn't.
|
||||
```cs
|
||||
// is it just turning monday now?
|
||||
var game = GameImpl.Instance;
|
||||
if (game.Weekday == DayOfWeek.Sunday && (game.CurrentTime + passedInGame).Days != game.CurrentTime.Days) {
|
||||
```
|
||||
|
||||
Clearly.
|
||||
```cs
|
||||
// if we're not loading from disk, we want to replace the floor with concrete
|
||||
if (initializeRooms) {
|
||||
```
|
||||
|
||||
*Am I wrong?*
|
||||
```cs
|
||||
// drywall should be considered ugly
|
||||
if (wall.Wallpapers[side].BaseName == "Default")
|
||||
rating--;
|
||||
```
|
||||
|
||||
I said it once (multiple times, actually), and I'll say it again: *Am I wrong?*
|
||||
```cs
|
||||
// energetic people should be able to stay awake longer than others
|
||||
public static readonly NeedType Energy = Register(new NeedType("Energy", 0.5F, p => ActionType.PassOut, p => p.HasPersonality(PersonalityType.Energetic) ? TimeSpan.FromHours(1) : TimeSpan.Zero, 10));
|
||||
```
|
||||
|
||||
There we go, that's most of the funny human-related comments I could find with the very simple search I did. I definitely think some of these are *very funny* out of context, but what makes it even better is that some of them are also pretty funny *in* context. Humans really do act very weirdly sometimes, don't they?
|
||||
|
||||
All of that being said, thanks so much for reading this blog post. If you haven't already, you should definitely check out the game, as it is very much a passion project of mine, and I think it currently has enough content to be quite a bit of fun to play already.
|
||||
|
||||
You can download the game for free (or for a price of your choosing) on its [itch page](https://ellpeck.itch.io/tiny-life).
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 🤡 One Year of Tiny Life, and Cursed Comment Time
|
||||
description: It's been exactly one year since I started working on my isometric Sims-style life simulation game Tiny Life, and since then, a lot has happened, especially in the realm of weird, funny and cursed comments in the code.
|
||||
tags: [Programming, Featured]
|
||||
discuss: https://ellpeck.itch.io/tiny-life/devlog/256839/one-year-of-tiny-life-and-cursed-comment-time
|
||||
---
|
||||
|
||||
On this day, exactly one year ago, I made my first commit to the Tiny Life repository. Since that first commit, which included some code for the isometric perspective that the game uses, Tiny Life has come *a long way*.
|
||||
|
||||
<img src="/blog/res/tiny_life_one_year/commit.png" width="100%">
|
||||
|
||||
If you don't recall just how long of a way it has come, or you don't even know about the game yet: Tiny Life is, as I wrote on its [itch page](https://ellpeck.itch.io/tiny-life):
|
||||
|
||||
> Tiny Life is a fun simulation game that tries to capture the essence of games like The Sims, but in an isometric pixelart style.
|
||||
>
|
||||
> In the game, you control a set of people that live together in a household. You take care of their daily needs, build their skills, forge new relationships... or just mess up their entire life in whatever way you can think of!
|
||||
|
||||
So, to celebrate, and because of a Twitter poll I did a while ago that made it clear that yall are interested in something like this, let's go through Tiny Life's current code and fish out some funny, cursed and weird code comments that just naturally come about when making a game that tries to simulate the personalities and behaviors of human people.
|
||||
|
||||
While this blog post *does* include a lot of programming-related humor, most of the comments are still funny and a bit ridiculous out of context, so you don't have to be a programmer to laugh along by any means.
|
||||
|
||||
<img src="/blog/res/tiny_life_one_year/search.png" width="100%">
|
||||
|
||||
That should do for now. *Oh, boy.* Note that I'll just be going through them using the order they appear in these search results, so the funniest ones won't be at the start or the end, but just... somewhere in between.
|
||||
|
||||
First up, this is one that most of you will probably find pretty relatable.
|
||||
```cs
|
||||
// we want people to clean dishes when they're hungry to make space for food
|
||||
Ai = {
|
||||
SolvedNeeds = new[] {NeedType.Hunger},
|
||||
}
|
||||
```
|
||||
|
||||
This one is for the introverts (to whom I most certainly belong) out there.
|
||||
```cs
|
||||
// we only want to visit someone when we're currently at home for long enough
|
||||
if (a)
|
||||
return i.Person.LotVisitCooldown <= TimeSpan.Zero && i.Person.LastVisitedLot == i.Person.HomeLot ? Valid : Hidden;
|
||||
|
||||
```
|
||||
|
||||
Teenagers should probably remember this one. Consent is (very unironically) important, yall!
|
||||
```cs
|
||||
// automatic romance interactions should only happen if we're already romantic towards each other
|
||||
return relationship?.RomanceLevel > 0 ? Valid : Hidden;
|
||||
```
|
||||
|
||||
Fair enough.
|
||||
```cs
|
||||
// eat food if we're hungry
|
||||
if (person.GetNeedPercentage(NeedType.Hunger) <= 0.5F && obj.ServingSize <= 1)
|
||||
return ActionType.Eat.Construct(person.GetHeldActionInfo());
|
||||
```
|
||||
|
||||
Especially in the city! Don't linger around too long, kids.
|
||||
```cs
|
||||
// move to the sidewalk once we're done driving
|
||||
var road = this.Map.GetClosestRoad(car.Position.ToPoint(), Map.RoadRadius + 1);
|
||||
```
|
||||
|
||||
You: Oh no, my car broke down!
|
||||
Me:
|
||||
```cs
|
||||
// if the driving fails, we always want to walk to the goal in the end
|
||||
return base.ShouldFail(completedAction, completion) && completedAction is not DriveAction;
|
||||
```
|
||||
|
||||
Do yall also do this thing where you're like "I cleaned *a single dish*, now I can take a break"?
|
||||
```cs
|
||||
// should we start to take a break between actions?
|
||||
if (this.OnBetweenActions(time, passedInGame, speed, current, completion)) {
|
||||
this.isBetweenActions = true;
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
It might be sad to hear, but this is something *you* have to do as well.
|
||||
```cs
|
||||
// we want to prioritize going to work over sleeping automatically
|
||||
if (this.StartedAutomatically && this.Person.Job != null && this.Person.Job.Type.IsTimeToWork(GameImpl.Instance.CurrentTime + TimeSpan.FromHours(1)))
|
||||
return CompletionType.Canceled;
|
||||
```
|
||||
|
||||
A bit creepy, don't you think?
|
||||
```cs
|
||||
// follow our partner until we reach them
|
||||
if (this.IsMain) {
|
||||
this.followTimer -= time.ElapsedGameTime;
|
||||
```
|
||||
|
||||
Jesus Christ, mom, how many more times do you want to tell me that *same story*?
|
||||
```cs
|
||||
// we add the recent social to the relationship of the recipient
|
||||
// so it represents an "I've heard this story already" list
|
||||
relationship.AddRecentSocial(action.Type);
|
||||
```
|
||||
|
||||
Also... fair enough.
|
||||
```cs
|
||||
// make lots more interesting if we have friends on them
|
||||
lot = Random.GetRandomWeightedEntry(lots, l => l.Type.GetVisitPriority(l, this.Person));
|
||||
```
|
||||
|
||||
It really *is* based on our mood how efficiently we work.
|
||||
```cs
|
||||
// if we're currently working, we should increase job performance based on our mood
|
||||
var performance = this.Person.Needs.Values.Count(n => n.Percentage >= 0.75F) * 0.004F;
|
||||
```
|
||||
|
||||
Does this also apply to *sleepovers*?
|
||||
```cs
|
||||
// the bed that we last slept in should be the one we try to sleep in again
|
||||
if (this.HasCategory(person, ObjectCategory.Bed) && categories.HasFlag(ObjectCategory.Bed) && this.Id == person.LastBedSleptIn)
|
||||
return 10;
|
||||
```
|
||||
|
||||
Fair... enough.
|
||||
```cs
|
||||
// pee puddles should be more disgusting
|
||||
DecorativeRating = f => f.Colors[0] == 1 ? -30 : -10
|
||||
```
|
||||
|
||||
For this one, I especially like that I chose to name the variable `naked`.
|
||||
```cs
|
||||
// if someone isn't wearing pants and they aren't romantic with us, we should get (them) embarrassed
|
||||
var naked = room.GetObjects<Person>()
|
||||
.Where(p => p != this && p.GetRelationship(this, false)?.RomancePercentage < 0.25F && !p.WornLayers.HasFlag(ClothesLayer.Pants))
|
||||
.ToArray();
|
||||
```
|
||||
|
||||
This comment is, of course, in the `Person.Die` method.
|
||||
```cs
|
||||
// make friends sad
|
||||
foreach (var rel in this.Relationships) {
|
||||
```
|
||||
|
||||
You: I'm bored!
|
||||
Me:
|
||||
```cs
|
||||
// if we don't have anything else to do, also try random actions
|
||||
if (this.person.ActionQueue.Count <= 0 && this.person.CurrentActions.Count <= 0)
|
||||
avail.AddRange(RandomActions);
|
||||
```
|
||||
|
||||
Drunk people, anyone?
|
||||
```cs
|
||||
// don't do stuff that's inappropriate here
|
||||
if (type.Settings.IsInappropriateElsewhere) {
|
||||
```
|
||||
|
||||
Am I wrong? I say no.
|
||||
```cs
|
||||
// the front door is the closest door to the mailbox that connects outside and inside
|
||||
var mailbox = this.GetObjects<Furniture>().FirstOrDefault(f => f.Type == FurnitureType.Mailbox);
|
||||
```
|
||||
|
||||
Oh no, I *really* hope it isn't.
|
||||
```cs
|
||||
// is it just turning monday now?
|
||||
var game = GameImpl.Instance;
|
||||
if (game.Weekday == DayOfWeek.Sunday && (game.CurrentTime + passedInGame).Days != game.CurrentTime.Days) {
|
||||
```
|
||||
|
||||
Clearly.
|
||||
```cs
|
||||
// if we're not loading from disk, we want to replace the floor with concrete
|
||||
if (initializeRooms) {
|
||||
```
|
||||
|
||||
*Am I wrong?*
|
||||
```cs
|
||||
// drywall should be considered ugly
|
||||
if (wall.Wallpapers[side].BaseName == "Default")
|
||||
rating--;
|
||||
```
|
||||
|
||||
I said it once (multiple times, actually), and I'll say it again: *Am I wrong?*
|
||||
```cs
|
||||
// energetic people should be able to stay awake longer than others
|
||||
public static readonly NeedType Energy = Register(new NeedType("Energy", 0.5F, p => ActionType.PassOut, p => p.HasPersonality(PersonalityType.Energetic) ? TimeSpan.FromHours(1) : TimeSpan.Zero, 10));
|
||||
```
|
||||
|
||||
There we go, that's most of the funny human-related comments I could find with the very simple search I did. I definitely think some of these are *very funny* out of context, but what makes it even better is that some of them are also pretty funny *in* context. Humans really do act very weirdly sometimes, don't they?
|
||||
|
||||
All of that being said, thanks so much for reading this blog post. If you haven't already, you should definitely check out the game, as it is very much a passion project of mine, and I think it currently has enough content to be quite a bit of fun to play already.
|
||||
|
||||
You can download the game for free (or for a price of your choosing) on its [itch page](https://ellpeck.itch.io/tiny-life).
|
||||
|
||||
❤, everyone.
|
|
@ -1,69 +1,69 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 🐶 Dog-Earing and Other Terrible Reading Habits
|
||||
summary: Since I've been reading a lot more in recent history, I thought I'd start writing some blog posts about the reading. So first up, here are some of my terrible reading habits that would probably make a lot of book lovers angry. This isn't clickbait. I'm just terrible.
|
||||
tags: [Reading]
|
||||
discuss: https://twitter.com/Ellpeck/status/1408565191218978818
|
||||
---
|
||||
|
||||
So recently, I've been reading a lot more again. Since I got my first Kindle [and talked about it](https://ellpeck.de/blog/reading) a while ago, I have now also started tracking my reading progress on [the StoryGraph](https://app.thestorygraph.com/profile/ellpeck). I also started watching some more book- and reading-related YouTube videos, and I came across this tag that I thought would be *perfect* for me to talk about for one specific reason, which I'll get to shortly.
|
||||
|
||||
To sum it up: My boyfriend thinks dog-earing books (that you own!) is the worst, and he despises me for doing it. But I want all of you to *hear my case* about this. So read on. Please.
|
||||
|
||||
# Do you have a certain place at home for reading?
|
||||
A while ago, I actually got one of those cheap-but-nice IKEA chairs that everyone seems to have and set it up as a little reading nook in a corner.
|
||||
|
||||
But then I realized that reading in bed, before going to sleep, actually works a lot better for me because I take sleeping pills, but they take a while to start working. So I got into the habit of taking them, and then reading for an hour or so in bed, and then putting the book away and dozing off right when I feel the medication starting to make me drowsy.
|
||||
|
||||
# Bookmark or random piece of paper?
|
||||
Okay, hear me out: *Dog-earing*. Of course, if you get a library book or read a friend's book, this is not a nice thing to do, because, after all, it *is* damaging someone else's property. In that case, a random piece of paper is a pretty good way to go, in my opinion.
|
||||
|
||||
*But.*
|
||||
|
||||
A book that looks like it's been read, with the pages a little warped and the spine maybe, possibly a little broken, and the marks of dog ears on some pages looks *so much nicer* than a book that looks all new and fancy and clean.
|
||||
|
||||
Listen, okay? Dog ears tell a *story*. Not only do they show you where you (or other people) took a reading break, but they also show you which parts of the book might have been difficult or otherwise slow to read, because those parts would have a lot more dog ears than other parts of the book.
|
||||
|
||||
Okay, maybe this is just me defending something that is objectively terrible. I like it, though.
|
||||
|
||||
# Can you just stop reading or do you have to stop after a chapter/ a certain amount of pages?
|
||||
I absolutely can't stop reading in the middle of a chapter. For me, it's not necessarily that I want to know how the chapter ends or that I enjoy stopping at the end of a chapter because it's a cliffhanger, and it'll make me feel excited to get back into the book later.
|
||||
|
||||
My real reason is a lot more boring, because it's just that... for some reason, it feels *wrong* stopping before the end of a chapter, similarly to how it feels wrong for some reason to stop watching a show in the middle of an episode.
|
||||
|
||||
Chapters were made for a reason, and the author probably thought about the pacing of the book and, as a result, the placement of the chapters. It doesn't feel like my place to just disrupt that pacing. And that placement.
|
||||
|
||||
# Do you eat or drink while reading?
|
||||
I don't think I've ever eaten while reading. It seems... unfitting. Especially because there are so many foods that make your fingers greasy or smudgy or... crumby. I wouldn't want to get that on my precious book. Or Kindle.
|
||||
|
||||
I do sometimes drink while reading, though. Especially when I prepared a little place and time to read, like when it's a nice day out, and I set aside some time to read and get a sunburn I mean suntan. I'll usually get a big glass of something nice. Yea.
|
||||
|
||||
# Multitasking: Music or TV while reading?
|
||||
I... do people do that? How? I don't have the mental capacity for that.
|
||||
|
||||
# One book at a time or several at once?
|
||||
I really *want* to be reading several books at once. I like the idea of reading one fiction book and one non-fiction book and then choosing which one to read based on how science-y I feel on any particular day. But whenever I try to start another book while I'm already reading one, I get one of two feelings: *The other book is so much more fun to read* or *This one is so much better than the other one*, both of which just make me end up reading just a single book again.
|
||||
|
||||
# Reading at home or everywhere?
|
||||
Since I mostly read on my Kindle, it would make a lot of sense for me to read in other, non-home places too. But I rarely do. Partly because, when focusing on something like a screen or a book for too long while riding a bus or a train makes me feel *incredibly* dizzy. But also partly because I read a lot of somewhat raunchy romance novels, talking about which, and showing the covers of which, in public sounds like *a time* for an introverted person like me.
|
||||
|
||||
# Reading out loud or silently in your head?
|
||||
I didn't realize there were people that read out loud, to be honest. It sounds kind of fun. I should try that.
|
||||
|
||||
# Do you read ahead or even skip pages?
|
||||
I used to read the end of a book right away when I was a little kid, because I was scared that the book would have a sad ending. Actually, I used to also *change* the endings of sad books by writing a nicer ending into the book to ease my mind. I was wholesome like that. I was also, like, 9. So ease off with the pitchforks.
|
||||
|
||||
Nowadays, I don't even really have the urge to find out what happens later on in the book. After all, the current part is already interesting, and I'll find out soon enough what happens in the future, I guess.
|
||||
|
||||
# Breaking the spine or keeping it like new?
|
||||
I will *absolutely* break the spine of any book I read (if I own it), because otherwise books are just too V-shaped to hold comfortably. It's not my fault that books are as flexible as a rock, okay? Do some yoga or something.
|
||||
|
||||
# Do you write in your books?
|
||||
Depends on the book. If it's a science-y book that I want to go back to, I'll definitely write notes and highlight sections in it. Since I mostly read on the Kindle, I'll actually highlight sections that I find funny or interesting to be able to get back to them later. Or to be able to share them with my boyfriend, who isn't *the least bit interested*.
|
||||
|
||||
# Conclusion
|
||||
I think my reading habits can be summed up pretty accurately as "book murderer". Which I'm honestly fine with.
|
||||
|
||||
I don't do it to books that aren't mine, though. I'm not, like, a library... hater. Or anything. Libraries are cool.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 🐶 Dog-Earing and Other Terrible Reading Habits
|
||||
description: Since I've been reading a lot more in recent history, I thought I'd start writing some blog posts about the reading. So first up, here are some of my terrible reading habits that would probably make a lot of book lovers angry. This isn't clickbait. I'm just terrible.
|
||||
tags: [Reading]
|
||||
discuss: https://twitter.com/Ellpeck/status/1408565191218978818
|
||||
---
|
||||
|
||||
So recently, I've been reading a lot more again. Since I got my first Kindle [and talked about it](https://ellpeck.de/blog/reading) a while ago, I have now also started tracking my reading progress on [the StoryGraph](https://app.thestorygraph.com/profile/ellpeck). I also started watching some more book- and reading-related YouTube videos, and I came across this tag that I thought would be *perfect* for me to talk about for one specific reason, which I'll get to shortly.
|
||||
|
||||
To sum it up: My boyfriend thinks dog-earing books (that you own!) is the worst, and he despises me for doing it. But I want all of you to *hear my case* about this. So read on. Please.
|
||||
|
||||
# Do you have a certain place at home for reading?
|
||||
A while ago, I actually got one of those cheap-but-nice IKEA chairs that everyone seems to have and set it up as a little reading nook in a corner.
|
||||
|
||||
But then I realized that reading in bed, before going to sleep, actually works a lot better for me because I take sleeping pills, but they take a while to start working. So I got into the habit of taking them, and then reading for an hour or so in bed, and then putting the book away and dozing off right when I feel the medication starting to make me drowsy.
|
||||
|
||||
# Bookmark or random piece of paper?
|
||||
Okay, hear me out: *Dog-earing*. Of course, if you get a library book or read a friend's book, this is not a nice thing to do, because, after all, it *is* damaging someone else's property. In that case, a random piece of paper is a pretty good way to go, in my opinion.
|
||||
|
||||
*But.*
|
||||
|
||||
A book that looks like it's been read, with the pages a little warped and the spine maybe, possibly a little broken, and the marks of dog ears on some pages looks *so much nicer* than a book that looks all new and fancy and clean.
|
||||
|
||||
Listen, okay? Dog ears tell a *story*. Not only do they show you where you (or other people) took a reading break, but they also show you which parts of the book might have been difficult or otherwise slow to read, because those parts would have a lot more dog ears than other parts of the book.
|
||||
|
||||
Okay, maybe this is just me defending something that is objectively terrible. I like it, though.
|
||||
|
||||
# Can you just stop reading or do you have to stop after a chapter/ a certain amount of pages?
|
||||
I absolutely can't stop reading in the middle of a chapter. For me, it's not necessarily that I want to know how the chapter ends or that I enjoy stopping at the end of a chapter because it's a cliffhanger, and it'll make me feel excited to get back into the book later.
|
||||
|
||||
My real reason is a lot more boring, because it's just that... for some reason, it feels *wrong* stopping before the end of a chapter, similarly to how it feels wrong for some reason to stop watching a show in the middle of an episode.
|
||||
|
||||
Chapters were made for a reason, and the author probably thought about the pacing of the book and, as a result, the placement of the chapters. It doesn't feel like my place to just disrupt that pacing. And that placement.
|
||||
|
||||
# Do you eat or drink while reading?
|
||||
I don't think I've ever eaten while reading. It seems... unfitting. Especially because there are so many foods that make your fingers greasy or smudgy or... crumby. I wouldn't want to get that on my precious book. Or Kindle.
|
||||
|
||||
I do sometimes drink while reading, though. Especially when I prepared a little place and time to read, like when it's a nice day out, and I set aside some time to read and get a sunburn I mean suntan. I'll usually get a big glass of something nice. Yea.
|
||||
|
||||
# Multitasking: Music or TV while reading?
|
||||
I... do people do that? How? I don't have the mental capacity for that.
|
||||
|
||||
# One book at a time or several at once?
|
||||
I really *want* to be reading several books at once. I like the idea of reading one fiction book and one non-fiction book and then choosing which one to read based on how science-y I feel on any particular day. But whenever I try to start another book while I'm already reading one, I get one of two feelings: *The other book is so much more fun to read* or *This one is so much better than the other one*, both of which just make me end up reading just a single book again.
|
||||
|
||||
# Reading at home or everywhere?
|
||||
Since I mostly read on my Kindle, it would make a lot of sense for me to read in other, non-home places too. But I rarely do. Partly because, when focusing on something like a screen or a book for too long while riding a bus or a train makes me feel *incredibly* dizzy. But also partly because I read a lot of somewhat raunchy romance novels, talking about which, and showing the covers of which, in public sounds like *a time* for an introverted person like me.
|
||||
|
||||
# Reading out loud or silently in your head?
|
||||
I didn't realize there were people that read out loud, to be honest. It sounds kind of fun. I should try that.
|
||||
|
||||
# Do you read ahead or even skip pages?
|
||||
I used to read the end of a book right away when I was a little kid, because I was scared that the book would have a sad ending. Actually, I used to also *change* the endings of sad books by writing a nicer ending into the book to ease my mind. I was wholesome like that. I was also, like, 9. So ease off with the pitchforks.
|
||||
|
||||
Nowadays, I don't even really have the urge to find out what happens later on in the book. After all, the current part is already interesting, and I'll find out soon enough what happens in the future, I guess.
|
||||
|
||||
# Breaking the spine or keeping it like new?
|
||||
I will *absolutely* break the spine of any book I read (if I own it), because otherwise books are just too V-shaped to hold comfortably. It's not my fault that books are as flexible as a rock, okay? Do some yoga or something.
|
||||
|
||||
# Do you write in your books?
|
||||
Depends on the book. If it's a science-y book that I want to go back to, I'll definitely write notes and highlight sections in it. Since I mostly read on the Kindle, I'll actually highlight sections that I find funny or interesting to be able to get back to them later. Or to be able to share them with my boyfriend, who isn't *the least bit interested*.
|
||||
|
||||
# Conclusion
|
||||
I think my reading habits can be summed up pretty accurately as "book murderer". Which I'm honestly fine with.
|
||||
|
||||
I don't do it to books that aren't mine, though. I'm not, like, a library... hater. Or anything. Libraries are cool.
|
||||
|
||||
Since I've been reading a lot more again in recent history, I also want to start writing more blog posts about my reading habits and the books I enjoy. If you're interested in that sort of thing, you can head back to [the post list](https://ellpeck.de/#blog-reading) to see other posts in the Reading category, and you can also subscribe to the blog's RSS feed there too. If anyone still does that. I think RSS is dead. Right?
|
|
@ -1,140 +1,140 @@
|
|||
---
|
||||
layout: blog
|
||||
title: 📦 Of Abby, Love and Butt-Shaped Pillows
|
||||
summary: "Jeremy had just moved into a new house when he found a mysterious, heart-shaped box in the attic. Intrigued by its contents, he started asking his neighbors about it, and he would soon discover a secret love story."
|
||||
tags: [Short Stories, Featured]
|
||||
book: true
|
||||
reedsy: https://blog.reedsy.com/short-story/qtt69j/
|
||||
discuss: https://twitter.com/Ellpeck/status/1494068545105416196
|
||||
---
|
||||
|
||||
Jeremy was sitting in his kitchen as suddenly, the room went dark.
|
||||
|
||||
Great. Two months living here, and the house is already falling apart. That was just Jeremy's luck, wasn't it?
|
||||
|
||||
He got up from one of his brand-new kitchen chairs and started making his way up the stairs to the attic, which is where he'd probably stored the light bulbs he brought from his old apartment. He didn't actually remember, mind you, because Jeremy hardly ever remembered anything. Jeremy was a man of few words, and a man of few thoughts.
|
||||
|
||||
Now standing on the wobbly ladder that folded down from the ceiling, he used most of the strength his body allowed him to lift a thick wooden board out of the way to reveal a hole in the ceiling to the attic. He climbed the scary ladder all the way and breathed in the stale air that had accumulated over all of those years that the house had stood on its own. After shuffling around some boxes with various words on them (like "kitchen" and "bathroom" and "heavy shit"), he finally spotted a small, transparent plastic box that contained a few light bulbs. Crouching into the corner to retrieve them, he noticed something he hadn't seen the few times that he'd been up here: A small, heart-shaped box, almost hidden entirely by the layers and layers of dust that were covering it.
|
||||
|
||||
Ready to reveal an old family secret or a bomb or, more realistically, just some weed in a little bag, he shuffled closer to the box and reached out to grab it. It was dusty. And kind of disgustingly sticky. Why was it *sticky*?
|
||||
|
||||
***
|
||||
|
||||
Light bulb changed, box dusted and un-sticked with a sponge that he now *desperately* wanted to throw away, Jeremy was ready to open it and reveal the weed-covered family bombs inside. The box was made of a thick cardboard-y substance (that was the technical term, he was sure), and dusting it revealed that it had been pink all this time.
|
||||
|
||||
The box contained several pieces of paper, a tiny, butt-shaped pillow that was probably supposed to look like a heart, and a silver necklace that represented half of a heart. Presumably, it was one of those where another person wore another one that was the opposite half, and it was a metaphor for their undying love, or a metaphor for the fact that a lot of people get divorced. Jeremy was never really sure. All in all, it was a lot of heart-shaped, love-related items, though.
|
||||
|
||||
But who had the other half of the necklace?
|
||||
|
||||
Clearly, this box had been meant for someone else. Obviously, it was not meant for *Jeremy*, but he knew that. He thought that it must've been meant for someone other than the person that had put it in his attic. Which was probably the previous owner of the house. Reading them, Jeremy quickly realized that the pieces of paper were actually letters. Love letters to someone named *Barb*. Was that even a *name*? Maybe it was short for Barbara?
|
||||
|
||||
There was one letter that stood out to him in particular. Most of the other ones seemed like they were just kind of *in* the box without actually belonging there (they were short notes about making plans and meeting up and holidays), but there was one that was clearly about this very box.
|
||||
|
||||
*My beloved Barb,*
|
||||
*Before you, I never met anyone who was quite as intoxicating, as filled with love, as passionate as you. I want you to know that, now and forever, I love you.*
|
||||
*I did not tell you this before, because I was scared. I was worried that you would not feel the same about me. I was worried about so many things. But now that our paths are about to part, and now that we might never see each other again, I need to give you this.*
|
||||
*It is all the things I could never give you. It is all the things I bought, and made, and wrote, and then stowed away instead of giving them to you. Because I was scared.*
|
||||
*But I will not be scared this time.*
|
||||
*I love you, Barb.*
|
||||
|
||||
Well. To say that Jeremy was moved by this letter was an understatement. Jeremy, as few words and thoughts as he had, he really had a lot of space in his heart. And clearly, Barb, whoever they were, had never received this box... right? In his head, he calculated how old this box could *possibly* be. None of the letters seemed to be dated, and none of the other items were food, so they didn't have expiration dates. The butt pillow had a little sign attached to it that was filled with washing instructions and small print, but also had the number 95 on it. Was it made in 1995? Maybe. Probably not, though. No one post-1995 was named Barbara, let alone *Barb*. And the previous owner had never mentioned a Barb, or a Barbara, or a barbarian, or anyone like that.
|
||||
|
||||
More importantly, what was he even going to do with this knowledge? And this box? Was he really going to spend his afternoon trying to figure out how to get it to its rightful recipient? And what were the ethics of doing that, anyway? What if this anonymous romantic had already moved on from Barb, probably to a person with a human name?
|
||||
|
||||
No, he was determined now. Jeremy loved love. He'd have done anything for love. Even chase down a person that might not exist based on some information from a sticky pink box.
|
||||
|
||||
One thing he knew for sure was the house's previous owner's name: Mariland Smith. Also not a human name, he noted. Maybe Mariland knew something about this box of butts and secrets.
|
||||
|
||||
Mariland was easy enough to reach, given he'd already talked to them a few times about the bathrooms and the piping and the power bills and the keys and how to get up to the attic. Weird then that they'd never mentioned a mystery box up there, though.
|
||||
|
||||
"A Barb, you say? Hmm," Mariland began after Jeremy told the story. Of course, Mariland didn't point out how peculiar the name Barb was because they had an equally ridiculous name. Instead, they pointed out that they'd rarely used the attic and that that was probably the reason they never saw the package. Made sense, Jeremy guessed.
|
||||
|
||||
After some silence, Mariland gasped.
|
||||
|
||||
"Actually, one of the neighbors did talk about a Barb from time to time. I think it was Mr. Garcia just down the road. You know, honey, I'm really sorry, but I didn't really know many of the people there."
|
||||
|
||||
Jeremy smiled. That was surprisingly helpful. "Thank you so much, that is honestly really helpful," he said earnestly, and after some goodbye-ing of the regular sort, he hung up.
|
||||
|
||||
***
|
||||
|
||||
Mr. Garcia, while being very old and exceptionally grumpy, actually had quite a bit of useful information for Jeremy. It wasn't the wild goose chase he feared to find out that Barb was, amazingly, short for *Abigail*, which seemed like some made-up shit to Jeremy. Maybe they read the first two letters backwards? And then added more random letters? Whatever.
|
||||
|
||||
A-barb-igail turned out to be an older lady that also used to live in the neighborhood, but Mr. Garcia didn't know whether she still did, or whether she was even still *alive*. How reassuring. He also made sure to point out to Jeremy that he'd never liked people like her, too eccentric, too loud, and too fully of energy. Thanks, Mr. Grumpy.
|
||||
|
||||
He made his way down the street to where Abigail-slash-Barb's house was meant to be. With Jeremy's luck, he'd probably find some ruins there, or a small forest, or a full-on black hole. What he really found was a small bungalow with washed-out, light blue side panels. It looked a lot smaller than his new house, but the roof looked a little less steep and the foundation seemed different, so he didn't know for sure.
|
||||
|
||||
He rang the doorbell, *praying* for the person opening to be Barb, with a sign hanging around her neck that says "Hello, I am Barb, and you don't have to speak to more people. This whole adventure was not a mistake, and it is now over, you have successfully found me." A short woman with a long ponytail opened the door. Jeremy introduced himself, and tried to get to the point as quickly as possible.
|
||||
|
||||
This was not Barb. Of course, it wasn't. It was Lucy. Jeremy told the story of the box, and the butt-shaped pillow, and the adorable note, and the half-heart-shaped necklace, and Lucy listened with wide eyes, and she was beaming.
|
||||
|
||||
"My gran... she never *knew*," she suddenly said. Wait, her *grandma*?
|
||||
|
||||
"Wait, y-your *grandma*?", he stammered.
|
||||
|
||||
She laughed. "Abigail. Yeah. I would always call her 'Granny Abby', but she tried to get everyone to call her Barb. I don't know why."
|
||||
|
||||
Jeremy sighed. She couldn't have said this at the start? When he asked about a Barb? Well, at least *Lucy* had a normal name.
|
||||
|
||||
"Down the road, you said? The green house?", she asked.
|
||||
|
||||
His new house wasn't really green anymore, since nobody had repainted it in a few years, probably even a decade. Jeremy didn't mind, because he never saw the outside much himself, and he couldn't care less what some strangers down the road thought of the state and dilapidation of his house.
|
||||
|
||||
"Yea, Maple 17," he replied.
|
||||
|
||||
"Evelyn Sherwood", she muttered somberly. "Her and Abby were best friends. Ever since I can remember, they spend most of their time together. Of course, no one thought about it at the time because an old lady like that--people thought she'd have herself figured out, I guess. Maybe they just didn't talk about it much back then, either."
|
||||
|
||||
Lucy had been staring into the hallway from where she was sitting, with a kind of intensity that implied she was focusing on something. But there was nothing there. What was she picturing?
|
||||
|
||||
"Yea, people had to be a lot quieter about it back then." He paused for a second to arrange his thoughts. All of a sudden, he had a lot of those. Emotions, too.
|
||||
|
||||
"The letter makes so much more sense to me now," he finally said. "She said that she was too scared to tell your grandma. Maybe it wasn't just about the anxiety for her."
|
||||
|
||||
"Yea," she said under her breath, which had become heavier. "I can't believe she never-"
|
||||
|
||||
Lucy let her head drop gently onto her folded arms, which were resting on the table. Jeremy sat there quietly, not knowing what to do. Surely, anything would be better than just sitting there like a fucking idiot, he thought. So he took the leap and trusted his instinct.
|
||||
|
||||
"I'm so sorry, Lucy," he said. He waited a second in an attempt to figure out if she heard him or not. "When did she pass?", he asked finally.
|
||||
|
||||
It took a few moments for Lucy to catch her breath. Awkwardly, she used the sleeves of her purple sweater to wipe away her tears, along with most of her makeup.
|
||||
|
||||
"It's been almost a year now," she muttered. "We're still not fine. I know it's- I know it seems pathetic, but my mom hasn't recovered yet, either. She never spent more than a week away."
|
||||
|
||||
Jeremy hastily searched his jacket and jeans pockets for a pack of tissues. Once he finally found it, he placed it on the table in front of her.
|
||||
|
||||
"It's not pathetic at all," he managed. He was awful at social situations, let alone situations in which someone was crying because they suffered a tragic loss. Jeremy was completely out of his depth here, but somehow, he still felt like he was managing fine.
|
||||
|
||||
"I know," she said sniffly. "It's just hard for us." She took one of the tissues. "Thanks."
|
||||
|
||||
Jeremy looked at Lucy as she blew her nose and used a second tissue to pat her face dry. It was a mess now, with her black eyeshadow having spread lines all over her face. But he didn't mind at all. He understood emotions well (at least he liked to think so), and he understood how hard it was to lose a loved one.
|
||||
|
||||
They sat for a little longer before Lucy recovered somewhat and went to make some tea for the two of them.
|
||||
|
||||
***
|
||||
|
||||
A few days had passed, and Jeremy found out a lot more about Barb, Evelyn and their story. He and Lucy had been talking frequently, and with every time she talked about their story, she seemed to lighten up more. It started out just like that first day, with her crying, and Jeremy feeling awful about asking in the first place. But as their conversations went on, Lucy started to seem excited about the love story that could have been.
|
||||
|
||||
That day, she called him on the phone while he was in the kitchen, sitting over his laptop and eating a bowl of cereal. He picked up the phone.
|
||||
|
||||
"Oh my *God*," Lucy immediately began on the other end, with a kind of excitement in her voice that Jeremy didn't think he'd heard from her yet. "I completely forgot that they went to the same *retirement home*!"
|
||||
|
||||
Retirement home? "Retirement home?", he asked out loud.
|
||||
|
||||
"Abby and Ev! Like five years ago, my mom got busier with her job because of some big promotion, and obviously I was at school all day, so my grandma decided to move into a home, and she visited home every weekend. But she talked about that place all the time, because Evelyn lived there and talked about it all the time! *That's* why she said in the letter that they might never meet again!"
|
||||
|
||||
Jeremy finally understood what she was implying, and he was smiling now. "Wait, and so you think-"
|
||||
|
||||
She didn't interrupt him, per se, as that was exactly what he'd wanted her to do. "*They shared a room*, Jer," she said, as if this was some big life-changing revelation for her. Maybe it was.
|
||||
|
||||
"Shared a *room*? I didn't even know you could do that in a retirement home," he said, half-surprised, half-excited.
|
||||
|
||||
"There is *no way* that Ev didn't admit it to her all that time. Absolutely no way. Jer, they were *literally roommates*, and none of us got it. Oh my God." Lucy seemed like she couldn't stop talking. It was all just flowing out of her, but Jeremy really enjoyed hearing her like this.
|
||||
|
||||
They talked for a little longer, and Lucy told more stories about Ev and Abby, and Jeremy loved listening to it all. He imagined her grandma and Evelyn, going on dates, and holding hands at the lake, and eating dinner together. Lucy imagined them sitting together, outside, on a porch swing, with their hands intertwined, looking out at the sunset. It was a perfect date straight out of a movie, the way she seemed to picture it.
|
||||
|
||||
After they both hung up, he finally finished his cereal, and he started thinking about the box again. Once he was done eating, he fetched it from on top of his kitchen cabinet, where he'd put it to avoid having to enter the attic again.
|
||||
|
||||
He grabbed the small, heart-shaped pillow out of the box and held it in his hand, squeezing it slightly. It was still kind of sticky, but this time around, Jeremy didn't seem to mind. Right now, he was feeling inexplicably brave.
|
||||
|
||||
He picked up his phone and started typing up a message to Lucy.
|
||||
|
||||
---
|
||||
layout: blog
|
||||
title: 📦 Of Abby, Love and Butt-Shaped Pillows
|
||||
description: "Jeremy had just moved into a new house when he found a mysterious, heart-shaped box in the attic. Intrigued by its contents, he started asking his neighbors about it, and he would soon discover a secret love story."
|
||||
tags: [Short Stories, Featured]
|
||||
book: true
|
||||
reedsy: https://blog.reedsy.com/short-story/qtt69j/
|
||||
discuss: https://twitter.com/Ellpeck/status/1494068545105416196
|
||||
---
|
||||
|
||||
Jeremy was sitting in his kitchen as suddenly, the room went dark.
|
||||
|
||||
Great. Two months living here, and the house is already falling apart. That was just Jeremy's luck, wasn't it?
|
||||
|
||||
He got up from one of his brand-new kitchen chairs and started making his way up the stairs to the attic, which is where he'd probably stored the light bulbs he brought from his old apartment. He didn't actually remember, mind you, because Jeremy hardly ever remembered anything. Jeremy was a man of few words, and a man of few thoughts.
|
||||
|
||||
Now standing on the wobbly ladder that folded down from the ceiling, he used most of the strength his body allowed him to lift a thick wooden board out of the way to reveal a hole in the ceiling to the attic. He climbed the scary ladder all the way and breathed in the stale air that had accumulated over all of those years that the house had stood on its own. After shuffling around some boxes with various words on them (like "kitchen" and "bathroom" and "heavy shit"), he finally spotted a small, transparent plastic box that contained a few light bulbs. Crouching into the corner to retrieve them, he noticed something he hadn't seen the few times that he'd been up here: A small, heart-shaped box, almost hidden entirely by the layers and layers of dust that were covering it.
|
||||
|
||||
Ready to reveal an old family secret or a bomb or, more realistically, just some weed in a little bag, he shuffled closer to the box and reached out to grab it. It was dusty. And kind of disgustingly sticky. Why was it *sticky*?
|
||||
|
||||
***
|
||||
|
||||
Light bulb changed, box dusted and un-sticked with a sponge that he now *desperately* wanted to throw away, Jeremy was ready to open it and reveal the weed-covered family bombs inside. The box was made of a thick cardboard-y substance (that was the technical term, he was sure), and dusting it revealed that it had been pink all this time.
|
||||
|
||||
The box contained several pieces of paper, a tiny, butt-shaped pillow that was probably supposed to look like a heart, and a silver necklace that represented half of a heart. Presumably, it was one of those where another person wore another one that was the opposite half, and it was a metaphor for their undying love, or a metaphor for the fact that a lot of people get divorced. Jeremy was never really sure. All in all, it was a lot of heart-shaped, love-related items, though.
|
||||
|
||||
But who had the other half of the necklace?
|
||||
|
||||
Clearly, this box had been meant for someone else. Obviously, it was not meant for *Jeremy*, but he knew that. He thought that it must've been meant for someone other than the person that had put it in his attic. Which was probably the previous owner of the house. Reading them, Jeremy quickly realized that the pieces of paper were actually letters. Love letters to someone named *Barb*. Was that even a *name*? Maybe it was short for Barbara?
|
||||
|
||||
There was one letter that stood out to him in particular. Most of the other ones seemed like they were just kind of *in* the box without actually belonging there (they were short notes about making plans and meeting up and holidays), but there was one that was clearly about this very box.
|
||||
|
||||
*My beloved Barb,*
|
||||
*Before you, I never met anyone who was quite as intoxicating, as filled with love, as passionate as you. I want you to know that, now and forever, I love you.*
|
||||
*I did not tell you this before, because I was scared. I was worried that you would not feel the same about me. I was worried about so many things. But now that our paths are about to part, and now that we might never see each other again, I need to give you this.*
|
||||
*It is all the things I could never give you. It is all the things I bought, and made, and wrote, and then stowed away instead of giving them to you. Because I was scared.*
|
||||
*But I will not be scared this time.*
|
||||
*I love you, Barb.*
|
||||
|
||||
Well. To say that Jeremy was moved by this letter was an understatement. Jeremy, as few words and thoughts as he had, he really had a lot of space in his heart. And clearly, Barb, whoever they were, had never received this box... right? In his head, he calculated how old this box could *possibly* be. None of the letters seemed to be dated, and none of the other items were food, so they didn't have expiration dates. The butt pillow had a little sign attached to it that was filled with washing instructions and small print, but also had the number 95 on it. Was it made in 1995? Maybe. Probably not, though. No one post-1995 was named Barbara, let alone *Barb*. And the previous owner had never mentioned a Barb, or a Barbara, or a barbarian, or anyone like that.
|
||||
|
||||
More importantly, what was he even going to do with this knowledge? And this box? Was he really going to spend his afternoon trying to figure out how to get it to its rightful recipient? And what were the ethics of doing that, anyway? What if this anonymous romantic had already moved on from Barb, probably to a person with a human name?
|
||||
|
||||
No, he was determined now. Jeremy loved love. He'd have done anything for love. Even chase down a person that might not exist based on some information from a sticky pink box.
|
||||
|
||||
One thing he knew for sure was the house's previous owner's name: Mariland Smith. Also not a human name, he noted. Maybe Mariland knew something about this box of butts and secrets.
|
||||
|
||||
Mariland was easy enough to reach, given he'd already talked to them a few times about the bathrooms and the piping and the power bills and the keys and how to get up to the attic. Weird then that they'd never mentioned a mystery box up there, though.
|
||||
|
||||
"A Barb, you say? Hmm," Mariland began after Jeremy told the story. Of course, Mariland didn't point out how peculiar the name Barb was because they had an equally ridiculous name. Instead, they pointed out that they'd rarely used the attic and that that was probably the reason they never saw the package. Made sense, Jeremy guessed.
|
||||
|
||||
After some silence, Mariland gasped.
|
||||
|
||||
"Actually, one of the neighbors did talk about a Barb from time to time. I think it was Mr. Garcia just down the road. You know, honey, I'm really sorry, but I didn't really know many of the people there."
|
||||
|
||||
Jeremy smiled. That was surprisingly helpful. "Thank you so much, that is honestly really helpful," he said earnestly, and after some goodbye-ing of the regular sort, he hung up.
|
||||
|
||||
***
|
||||
|
||||
Mr. Garcia, while being very old and exceptionally grumpy, actually had quite a bit of useful information for Jeremy. It wasn't the wild goose chase he feared to find out that Barb was, amazingly, short for *Abigail*, which seemed like some made-up shit to Jeremy. Maybe they read the first two letters backwards? And then added more random letters? Whatever.
|
||||
|
||||
A-barb-igail turned out to be an older lady that also used to live in the neighborhood, but Mr. Garcia didn't know whether she still did, or whether she was even still *alive*. How reassuring. He also made sure to point out to Jeremy that he'd never liked people like her, too eccentric, too loud, and too fully of energy. Thanks, Mr. Grumpy.
|
||||
|
||||
He made his way down the street to where Abigail-slash-Barb's house was meant to be. With Jeremy's luck, he'd probably find some ruins there, or a small forest, or a full-on black hole. What he really found was a small bungalow with washed-out, light blue side panels. It looked a lot smaller than his new house, but the roof looked a little less steep and the foundation seemed different, so he didn't know for sure.
|
||||
|
||||
He rang the doorbell, *praying* for the person opening to be Barb, with a sign hanging around her neck that says "Hello, I am Barb, and you don't have to speak to more people. This whole adventure was not a mistake, and it is now over, you have successfully found me." A short woman with a long ponytail opened the door. Jeremy introduced himself, and tried to get to the point as quickly as possible.
|
||||
|
||||
This was not Barb. Of course, it wasn't. It was Lucy. Jeremy told the story of the box, and the butt-shaped pillow, and the adorable note, and the half-heart-shaped necklace, and Lucy listened with wide eyes, and she was beaming.
|
||||
|
||||
"My gran... she never *knew*," she suddenly said. Wait, her *grandma*?
|
||||
|
||||
"Wait, y-your *grandma*?", he stammered.
|
||||
|
||||
She laughed. "Abigail. Yeah. I would always call her 'Granny Abby', but she tried to get everyone to call her Barb. I don't know why."
|
||||
|
||||
Jeremy sighed. She couldn't have said this at the start? When he asked about a Barb? Well, at least *Lucy* had a normal name.
|
||||
|
||||
"Down the road, you said? The green house?", she asked.
|
||||
|
||||
His new house wasn't really green anymore, since nobody had repainted it in a few years, probably even a decade. Jeremy didn't mind, because he never saw the outside much himself, and he couldn't care less what some strangers down the road thought of the state and dilapidation of his house.
|
||||
|
||||
"Yea, Maple 17," he replied.
|
||||
|
||||
"Evelyn Sherwood", she muttered somberly. "Her and Abby were best friends. Ever since I can remember, they spend most of their time together. Of course, no one thought about it at the time because an old lady like that--people thought she'd have herself figured out, I guess. Maybe they just didn't talk about it much back then, either."
|
||||
|
||||
Lucy had been staring into the hallway from where she was sitting, with a kind of intensity that implied she was focusing on something. But there was nothing there. What was she picturing?
|
||||
|
||||
"Yea, people had to be a lot quieter about it back then." He paused for a second to arrange his thoughts. All of a sudden, he had a lot of those. Emotions, too.
|
||||
|
||||
"The letter makes so much more sense to me now," he finally said. "She said that she was too scared to tell your grandma. Maybe it wasn't just about the anxiety for her."
|
||||
|
||||
"Yea," she said under her breath, which had become heavier. "I can't believe she never-"
|
||||
|
||||
Lucy let her head drop gently onto her folded arms, which were resting on the table. Jeremy sat there quietly, not knowing what to do. Surely, anything would be better than just sitting there like a fucking idiot, he thought. So he took the leap and trusted his instinct.
|
||||
|
||||
"I'm so sorry, Lucy," he said. He waited a second in an attempt to figure out if she heard him or not. "When did she pass?", he asked finally.
|
||||
|
||||
It took a few moments for Lucy to catch her breath. Awkwardly, she used the sleeves of her purple sweater to wipe away her tears, along with most of her makeup.
|
||||
|
||||
"It's been almost a year now," she muttered. "We're still not fine. I know it's- I know it seems pathetic, but my mom hasn't recovered yet, either. She never spent more than a week away."
|
||||
|
||||
Jeremy hastily searched his jacket and jeans pockets for a pack of tissues. Once he finally found it, he placed it on the table in front of her.
|
||||
|
||||
"It's not pathetic at all," he managed. He was awful at social situations, let alone situations in which someone was crying because they suffered a tragic loss. Jeremy was completely out of his depth here, but somehow, he still felt like he was managing fine.
|
||||
|
||||
"I know," she said sniffly. "It's just hard for us." She took one of the tissues. "Thanks."
|
||||
|
||||
Jeremy looked at Lucy as she blew her nose and used a second tissue to pat her face dry. It was a mess now, with her black eyeshadow having spread lines all over her face. But he didn't mind at all. He understood emotions well (at least he liked to think so), and he understood how hard it was to lose a loved one.
|
||||
|
||||
They sat for a little longer before Lucy recovered somewhat and went to make some tea for the two of them.
|
||||
|
||||
***
|
||||
|
||||
A few days had passed, and Jeremy found out a lot more about Barb, Evelyn and their story. He and Lucy had been talking frequently, and with every time she talked about their story, she seemed to lighten up more. It started out just like that first day, with her crying, and Jeremy feeling awful about asking in the first place. But as their conversations went on, Lucy started to seem excited about the love story that could have been.
|
||||
|
||||
That day, she called him on the phone while he was in the kitchen, sitting over his laptop and eating a bowl of cereal. He picked up the phone.
|
||||
|
||||
"Oh my *God*," Lucy immediately began on the other end, with a kind of excitement in her voice that Jeremy didn't think he'd heard from her yet. "I completely forgot that they went to the same *retirement home*!"
|
||||
|
||||
Retirement home? "Retirement home?", he asked out loud.
|
||||
|
||||
"Abby and Ev! Like five years ago, my mom got busier with her job because of some big promotion, and obviously I was at school all day, so my grandma decided to move into a home, and she visited home every weekend. But she talked about that place all the time, because Evelyn lived there and talked about it all the time! *That's* why she said in the letter that they might never meet again!"
|
||||
|
||||
Jeremy finally understood what she was implying, and he was smiling now. "Wait, and so you think-"
|
||||
|
||||
She didn't interrupt him, per se, as that was exactly what he'd wanted her to do. "*They shared a room*, Jer," she said, as if this was some big life-changing revelation for her. Maybe it was.
|
||||
|
||||
"Shared a *room*? I didn't even know you could do that in a retirement home," he said, half-surprised, half-excited.
|
||||
|
||||
"There is *no way* that Ev didn't admit it to her all that time. Absolutely no way. Jer, they were *literally roommates*, and none of us got it. Oh my God." Lucy seemed like she couldn't stop talking. It was all just flowing out of her, but Jeremy really enjoyed hearing her like this.
|
||||
|
||||
They talked for a little longer, and Lucy told more stories about Ev and Abby, and Jeremy loved listening to it all. He imagined her grandma and Evelyn, going on dates, and holding hands at the lake, and eating dinner together. Lucy imagined them sitting together, outside, on a porch swing, with their hands intertwined, looking out at the sunset. It was a perfect date straight out of a movie, the way she seemed to picture it.
|
||||
|
||||
After they both hung up, he finally finished his cereal, and he started thinking about the box again. Once he was done eating, he fetched it from on top of his kitchen cabinet, where he'd put it to avoid having to enter the attic again.
|
||||
|
||||
He grabbed the small, heart-shaped pillow out of the box and held it in his hand, squeezing it slightly. It was still kind of sticky, but this time around, Jeremy didn't seem to mind. Right now, he was feeling inexplicably brave.
|
||||
|
||||
He picked up his phone and started typing up a message to Lucy.
|
||||
|
||||
"Speaking of perfect dates," he started. "Wanna see a movie tonight?"
|
|
@ -1,20 +1,20 @@
|
|||
---
|
||||
layout: default
|
||||
title: Impressum
|
||||
summary: Impressum
|
||||
nav: nav/miscnav.html
|
||||
---
|
||||
|
||||
<div class="list-display rounded">
|
||||
<h1>📜 Impressum</h1>
|
||||
<p>
|
||||
Julian Schubert
|
||||
<br>Meininger Allee 9
|
||||
<br>89231 Neu-Ulm
|
||||
</p>
|
||||
<p>
|
||||
Telefon: 0241 45093753
|
||||
<br>E-Mail: me@ellpeck.de
|
||||
</p>
|
||||
<p>Die obenstehende Person ist ebenfalls verantwortlich für den Inhalt (gem. § 55 Abs. 2 RStV).</p>
|
||||
---
|
||||
layout: default
|
||||
title: Impressum
|
||||
description: Impressum
|
||||
nav: nav/miscnav.html
|
||||
---
|
||||
|
||||
<div class="list-display rounded">
|
||||
<h1>📜 Impressum</h1>
|
||||
<p>
|
||||
Julian Schubert
|
||||
<br>Meininger Allee 9
|
||||
<br>89231 Neu-Ulm
|
||||
</p>
|
||||
<p>
|
||||
Telefon: 0241 45093753
|
||||
<br>E-Mail: me@ellpeck.de
|
||||
</p>
|
||||
<p>Die obenstehende Person ist ebenfalls verantwortlich für den Inhalt (gem. § 55 Abs. 2 RStV).</p>
|
||||
</div>
|
|
@ -1,28 +1,28 @@
|
|||
---
|
||||
layout: default
|
||||
title: Ellpeck.de
|
||||
summary: Ellpeck's little internet place
|
||||
nav: nav/indexnav.html
|
||||
---
|
||||
|
||||
<!-- Home -->
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-auto">
|
||||
<img src="./res/me.jpeg" class="rounded-circle" width="150" height="150" id="navbar-image" alt="A cover photo of Ellpeck">
|
||||
</div>
|
||||
<div class="col">
|
||||
<h1 class="display-4" id="intro-text"></h1>
|
||||
<script src="./scripts/greet.js"></script>
|
||||
<p class="lead">Welcome to my little website! I'm Ellpeck, a student and programmer from Germany. I do a lot of stuff, actually. My life is pretty busy.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include projects.html %}
|
||||
{% include social.html %}
|
||||
{% include about.html %}
|
||||
{% include blog.html %}
|
||||
---
|
||||
layout: default
|
||||
title: Ellpeck.de
|
||||
description: Ellpeck's little internet place
|
||||
nav: nav/indexnav.html
|
||||
---
|
||||
|
||||
<!-- Home -->
|
||||
<div class="jumbotron">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-auto">
|
||||
<img src="./res/me.jpeg" class="rounded-circle" width="150" height="150" id="navbar-image" alt="A cover photo of Ellpeck">
|
||||
</div>
|
||||
<div class="col">
|
||||
<h1 class="display-4" id="intro-text"></h1>
|
||||
<script src="./scripts/greet.js"></script>
|
||||
<p class="lead">Welcome to my little website! I'm Ellpeck, a student and programmer from Germany. I do a lot of stuff, actually. My life is pretty busy.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include projects.html %}
|
||||
{% include social.html %}
|
||||
{% include about.html %}
|
||||
{% include blog.html %}
|
||||
{% include support.html %}
|
|
@ -1,26 +1,26 @@
|
|||
---
|
||||
layout: default
|
||||
title: Privacy Policy
|
||||
summary: Privacy Policy
|
||||
nav: nav/miscnav.html
|
||||
---
|
||||
|
||||
<div class="list-display rounded">
|
||||
<h1>🙈 Privacy Policy</h1>
|
||||
<p>This site uses cookies to store information about your browsing activity.</p>
|
||||
<p>Ellpeck.de stores the following information:</p>
|
||||
<ul>
|
||||
<li>A cookie named <code>dark</code> with the value <code>true</code> or <code>false</code> that stores if you have dark mode enabled</li>
|
||||
<li>A cookie named <code>notification</code> with the value <code>true</code> or <code>false</code> that stores if you have already closed the cookie notification that displays at the top of the page</li>
|
||||
</ul>
|
||||
<p>Due to widgets and embeds, additional information will be stored by other sites. Please refer to those sites' privacy policies for more information:</p>
|
||||
<ul>
|
||||
<li>Google uses cookies to serve ads based on a user's prior visits to this website. You may opt out of personal advertising by visiting <a href="https://www.google.com/settings/ads">Ad Settings</a>. For more information, see <a href="http://www.google.com/policies/privacy/partners/">how Google uses data when you use its partners' sites or apps</a>.</li>
|
||||
<li>Discord uses cookies for its widget embed. For more information, see <a href="https://discordapp.com/privacy">their privacy policy</a>.</li>
|
||||
<li>Twitter uses cookies for its tweet embeds. For more information, see <a href="https://twitter.com/en/privacy">their privacy policy</a>.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Transparency is very important to us, and as such, if you have any doubts about the security of this website, you can view its source code <a href="https://git.ellpeck.de/Ellpeck/Web">on Gitea</a>.
|
||||
<br>Keep in mind that you can also review or delete stored cookies for any site at any time in your browser's settings.
|
||||
</p>
|
||||
---
|
||||
layout: default
|
||||
title: Privacy Policy
|
||||
description: Privacy Policy
|
||||
nav: nav/miscnav.html
|
||||
---
|
||||
|
||||
<div class="list-display rounded">
|
||||
<h1>🙈 Privacy Policy</h1>
|
||||
<p>This site uses cookies to store information about your browsing activity.</p>
|
||||
<p>Ellpeck.de stores the following information:</p>
|
||||
<ul>
|
||||
<li>A cookie named <code>dark</code> with the value <code>true</code> or <code>false</code> that stores if you have dark mode enabled</li>
|
||||
<li>A cookie named <code>notification</code> with the value <code>true</code> or <code>false</code> that stores if you have already closed the cookie notification that displays at the top of the page</li>
|
||||
</ul>
|
||||
<p>Due to widgets and embeds, additional information will be stored by other sites. Please refer to those sites' privacy policies for more information:</p>
|
||||
<ul>
|
||||
<li>Google uses cookies to serve ads based on a user's prior visits to this website. You may opt out of personal advertising by visiting <a href="https://www.google.com/settings/ads">Ad Settings</a>. For more information, see <a href="http://www.google.com/policies/privacy/partners/">how Google uses data when you use its partners' sites or apps</a>.</li>
|
||||
<li>Discord uses cookies for its widget embed. For more information, see <a href="https://discordapp.com/privacy">their privacy policy</a>.</li>
|
||||
<li>Twitter uses cookies for its tweet embeds. For more information, see <a href="https://twitter.com/en/privacy">their privacy policy</a>.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Transparency is very important to us, and as such, if you have any doubts about the security of this website, you can view its source code <a href="https://git.ellpeck.de/Ellpeck/Web">on Gitea</a>.
|
||||
<br>Keep in mind that you can also review or delete stored cookies for any site at any time in your browser's settings.
|
||||
</p>
|
||||
</div>
|
Loading…
Reference in a new issue